]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
13493d78ea25ee2939ac3e6861d1aec00097106e
[tmp/jakarta-migration.git] /
1 package org.collectionspace.services.client.test;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.List;
6 import java.util.Map;
7
8 import javax.ws.rs.core.Response;
9
10 import org.apache.http.HttpStatus;
11 import org.collectionspace.services.client.AbstractCommonListUtils;
12 import org.collectionspace.services.client.AuthorityClient;
13 import org.collectionspace.services.client.CollectionSpaceClient;
14 import org.collectionspace.services.client.PayloadInputPart;
15 import org.collectionspace.services.client.PoxPayloadIn;
16 import org.collectionspace.services.client.PoxPayloadOut;
17 import org.collectionspace.services.client.RelationClient;
18 import org.collectionspace.services.client.XmlTools;
19 import org.collectionspace.services.client.workflow.WorkflowClient;
20 import org.collectionspace.services.description.ServiceDescription;
21 import org.collectionspace.services.jaxb.AbstractCommonList;
22 import org.collectionspace.services.relation.RelationsCommon;
23 import org.collectionspace.services.relation.RelationsCommonList;
24 import org.collectionspace.services.relation.RelationsCommonList.RelationListItem;
25 import org.collectionspace.services.relation.RelationshipType;
26 import org.dom4j.Document;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29 import org.testng.Assert;
30 import org.testng.SkipException;
31 import org.testng.annotations.Test;
32
33 /**
34  * 
35  * @author remillet
36  *
37  * @param <AUTHORITY_COMMON_TYPE>
38  * @param <AUTHORITY_ITEM_TYPE>
39  * 
40  * All CRUD related authority test classes should extend this class.
41  * 
42  */
43 @SuppressWarnings("rawtypes")
44 public abstract class AbstractAuthorityServiceTest<AUTHORITY_COMMON_TYPE, AUTHORITY_ITEM_TYPE> 
45         extends AbstractPoxServiceTestImpl<AbstractCommonList, AUTHORITY_COMMON_TYPE> {
46
47     private final Logger logger = LoggerFactory.getLogger(AbstractAuthorityServiceTest.class);
48         
49     protected String knownResourceShortIdentifer = null;
50         protected static final String READITEMS_SHORT_IDENTIFIER = "resourceWithItems" + random.nextInt(1000); 
51         protected String knownAuthorityWithItems = null;
52         protected String knownAuthorityWithItemsIdentifier = null;
53         
54         protected static final String SAS_IDENTIFIER = "SAS";
55         protected static final String SAS_WITH_RELATIONS = "_RELATIONS_"; 
56
57         private static final int SAS_ITEMLIST_SIZE = 5;
58
59         protected String knownSASAuthorityResourceId = null;
60         protected String knownSASAuthorityResourceShortId = null;
61         protected List<String> knownSASItemIdentifiersList = new ArrayList<String>();
62         protected String knownSASItemResourceId = null;
63         protected HashMap<String, String> allSASResourceItemIdsCreated = new HashMap<String, String>(); /* itemURN, parentURN */;
64
65         protected String knownResourceRefName = null;
66     protected String knownItemResourceId = null;
67     protected String knownItemResourceShortIdentifer = null;    
68     protected int nItemsToCreateInList = 5;
69     protected String TEST_SHORTID = "johnWayneActor";
70
71         protected List<String> knownSASItemIdentifiersWithRelationsList = new ArrayList<String>();
72         protected String knownSASAuthorityResourceWithRelationsId = null;
73         protected String knownSASAuthorityResourceWithRelationsShortId = null;
74
75         //
76         // Used to test hierarchical relationship synchronization
77         //
78         private String continentShortId;
79         private String countryShortId;
80         private String cityShortId;
81
82     /*
83      * Abstract methods that subclasses must override/implement
84      */
85     
86     /**
87      * 
88      * @param testName
89      */
90     public abstract void authorityTests(String testName);
91         
92         /**
93          * 
94          * @param client
95          * @param vcsid
96          * @return
97          * @throws Exception 
98          */
99         abstract protected String createItemInAuthority(AuthorityClient client, String vcsid, String shortId) throws Exception;
100         
101     
102     /**
103      * 
104      * @param authorityItem
105      * @return
106      */
107     protected abstract AUTHORITY_ITEM_TYPE updateItemInstance(final AUTHORITY_ITEM_TYPE authorityItem);    
108     
109     /**
110      * 
111      * @param original
112      * @param updated
113      * @throws Exception
114      */
115     protected abstract void compareUpdatedItemInstances(AUTHORITY_ITEM_TYPE original,
116                 AUTHORITY_ITEM_TYPE updated,
117                 boolean compareRevNumbers) throws Exception;
118     
119     /**
120      * 
121      * @param original
122      * @param updated
123      * @throws Exception
124      */
125     protected void compareUpdatedItemInstances(AUTHORITY_ITEM_TYPE original,
126                 AUTHORITY_ITEM_TYPE updated) throws Exception {
127         compareUpdatedItemInstances(original, updated, false);
128     }
129     
130     /**
131      * 
132      * @param id
133      * @param shortIdentifer
134      */
135     protected void setKnownItemResource(String id, String shortIdentifer ) {
136         knownItemResourceId = id;
137         knownItemResourceShortIdentifer = shortIdentifer;
138     }
139
140     /**
141      * 
142      * @param id
143      * @param shortIdentifer
144      * @param refName
145      */
146     protected void setKnownResource(String id, String shortIdentifer,
147             String refName) {
148         knownResourceId = id;
149         knownResourceShortIdentifer = shortIdentifer;
150         knownResourceRefName = refName;
151     }
152
153     /**
154      * 
155      * @return
156      */
157         protected String getSASAuthorityIdentifier() {
158                 return this.getKnowResourceIdentifier() + SAS_IDENTIFIER;
159         }
160     
161     /**
162      * 
163      * @return
164      */
165         protected String getSASAuthorityWithRelationsIdentifier() {
166                 return this.getKnowResourceIdentifier() + SAS_WITH_RELATIONS + SAS_IDENTIFIER;
167         }
168     
169         /**
170          * 
171          * @param shortId
172          * @return
173          */
174         protected String getUrnIdentifier(String shortId) {
175                 return String.format("urn:cspace:name(%s)", shortId);
176         }
177         
178         /*
179          * Returns the CSID using the authority short ID.  Passed in client must be for the correct authority type -i.e., the on
180          * that corresponds to the CSID.
181          */
182         protected String getCsidFromShortId(AuthorityClient client, String authShortId, String itemShortId) {
183                 String result = null;
184                 
185                 Response res = client.readNamedItemInNamedAuthority(authShortId, itemShortId);
186                 try {
187                         result = extractCsid(res);
188                 } catch (Exception e) {
189                         logger.error(String.format("Could not get CSID for authority item '%s' in authority '%s' of type '%s'.",
190                                         itemShortId, authShortId, client.getServiceName()), e);
191                 } finally {
192                         res.close();
193                 }
194                 
195                 return result;
196         }
197
198         
199     /**
200      * Sets up create tests.
201      */
202     protected void setupSync() {
203         testExpectedStatusCode = STATUS_OK;
204         testRequestType = ServiceRequestType.SYNC;
205         testSetup(testExpectedStatusCode, testRequestType);
206     }
207     
208     /**
209      * Gets a client to the SAS (Shared Authority Server)
210      *
211      * @return the client
212      * @throws Exception 
213      */
214         protected AuthorityClient getSASClientInstance() throws Exception {
215         return (AuthorityClient) this.getClientInstance(CollectionSpaceClient.SAS_CLIENT_PROPERTIES_FILENAME);
216     }
217
218     /**
219      * Returns the root URL for a service.
220      *
221      * This URL consists of a base URL for all services, followed by
222      * a path component for the owning vocabulary, followed by the 
223      * path component for the items.
224      *
225      * @return The root URL for a service.
226      */
227     protected String getItemServiceRootURL(String parentResourceIdentifier) {
228         return getResourceURL(parentResourceIdentifier) + "/" + getServicePathItemsComponent();
229     }
230
231     /**
232      * Returns the URL of a specific resource managed by a service, and
233      * designated by an identifier (such as a universally unique ID, or UUID).
234      *
235      * @param  resourceIdentifier  An identifier (such as a UUID) for a resource.
236      *
237      * @return The URL of a specific resource managed by a service.
238      */
239     protected String getItemResourceURL(String parentResourceIdentifier, String resourceIdentifier) {
240         return getItemServiceRootURL(parentResourceIdentifier) + "/" + resourceIdentifier;
241     }
242         
243     /**
244      * For authorities we override this method so we can save the shortid.
245      */
246     @Override
247     protected String createWithIdentifier(String testName, String identifier) throws Exception {
248         String csid = createResource(testName, identifier);
249         // Store the ID returned from the first resource created
250         // for additional tests below.
251         if (getKnowResourceId() == null) {
252                 setKnownResource(csid, identifier /*shortId*/, null /*refname*/ );
253             if (logger.isDebugEnabled()) {
254                 logger.debug(testName + ": Setting knownResourceId=" + getKnowResourceId());
255             }
256         }
257         
258         return identifier;
259     }    
260     
261     @Test(dependsOnMethods = {"readItem", "CRUDTests"})
262     public void testItemSubmitRequest() {
263
264         // Expected status code: 200 OK
265         final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
266
267         // Submit the request to the service and store the response.
268         String method = ServiceRequestType.READ.httpMethodName();
269         String url = getItemResourceURL(knownResourceId, knownItemResourceId);
270         int statusCode = submitRequest(method, url);
271
272         // Check the status code of the response: does it match
273         // the expected response(s)?
274         if (logger.isDebugEnabled()) {
275             logger.debug("testItemSubmitRequest: url=" + url
276                     + " status=" + statusCode);
277         }
278         Assert.assertEquals(statusCode, EXPECTED_STATUS);
279     }    
280
281         @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
282         dependsOnMethods = {"readItem"})
283     public void verifyIgnoredUpdateWithInAuthority(String testName) throws Exception {
284         // Perform setup.
285         setupUpdate();
286
287         // Submit the request to the service and store the response.
288         AuthorityClient client = (AuthorityClient)this.getClientInstance();
289         Response res = client.readItem(knownResourceId, knownItemResourceId);
290         AUTHORITY_ITEM_TYPE vitem = null;
291         try {
292                 int statusCode = res.getStatus();
293         
294                 // Check the status code of the response: does it match
295                 // the expected response(s)?
296                 if (logger.isDebugEnabled()) {
297                         logger.debug(testName + " read authority:" + knownResourceId + "/Item:"
298                                         + knownItemResourceId + " status = " + statusCode);
299                 }
300                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
301                                 invalidStatusCodeMessage(testRequestType, statusCode));
302                 Assert.assertEquals(statusCode, Response.Status.OK.getStatusCode());
303         
304                 vitem = extractItemCommonPartValue(res);
305                 Assert.assertNotNull(vitem);
306                 // Try to Update with new parent vocab (use self, for test).
307                 Assert.assertEquals(client.getInAuthority(vitem), knownResourceId,
308                                 "VocabularyItem inAuthority does not match knownResourceId.");
309                 client.setInAuthority(vitem, knownItemResourceId);
310
311         } finally {
312                 res.close();
313         }
314         
315         // Submit the updated resource to the service and store the response.
316         PoxPayloadOut output = this.createItemRequestTypeInstance(vitem);
317         res = client.updateItem(knownResourceId, knownItemResourceId, output);
318         try {
319                 int statusCode = res.getStatus();
320         
321                 // Check the status code of the response: does it match the expected response(s)?
322                 if (logger.isDebugEnabled()) {
323                         logger.debug(testName + ": status = " + statusCode);
324                 }
325                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
326                                 invalidStatusCodeMessage(testRequestType, statusCode));
327                 Assert.assertEquals(statusCode, testExpectedStatusCode);
328         } finally {
329                 res.close();
330         }
331         
332         res = client.readItem(knownResourceId, knownItemResourceId);
333         try {
334                 // Retrieve the updated resource and verify that the parent did not change
335                 AUTHORITY_ITEM_TYPE updatedVocabularyItem = extractItemCommonPartValue(res);
336                 Assert.assertNotNull(updatedVocabularyItem);
337         
338                 // Verify that the updated resource received the correct data.
339                 Assert.assertEquals(client.getInAuthority(updatedVocabularyItem),
340                                 knownResourceId,
341                                 "VocabularyItem allowed update to the parent (inAuthority).");
342         } finally {
343                 res.close();
344         }
345     }
346     
347         @Test(dataProvider = "testName", dependsOnMethods = {"CRUDTests"})
348     public void createItem(String testName) throws Exception {
349         // Perform setup.
350         setupCreate();
351         String newID = createItemInAuthority((AuthorityClient) getClientInstance(), knownResourceId, getTestAuthorityItemShortId());
352
353         // Store the ID returned from the first item resource created
354         // for additional tests below.
355         if (knownItemResourceId == null) {
356             knownItemResourceId = newID;
357             if (null != testName && logger.isDebugEnabled()) {
358                 logger.debug(testName + ": knownItemResourceId=" + knownItemResourceId);
359             }
360         }
361     }
362         
363         @Test(dataProvider = "testName", dependsOnMethods = {"readItem", "CRUDTests"})
364     public void checkAuthorityWorkflowTransitions(String testName) throws Exception {
365         //
366         // First check to see if the authority supports synchronization -i.e., the "cs_replicating" lifecycle policy.
367         //
368         assertSupportsSync();
369                 
370         String itemCsid = createItemInAuthority((AuthorityClient) getClientInstance(), knownResourceId, getTestAuthorityItemShortId() + testName);
371         // Add workflow states
372         updateItemLifeCycleState(testName, knownResourceId, itemCsid, WorkflowClient.WORKFLOWTRANSITION_REPLICATE, WorkflowClient.WORKFLOWSTATE_REPLICATED);
373         updateItemLifeCycleState(testName, knownResourceId, itemCsid, WorkflowClient.WORKFLOWTRANSITION_DEPRECATE, WorkflowClient.WORKFLOWSTATE_REPLICATED_DEPRECATED);
374         updateItemLifeCycleState(testName, knownResourceId, itemCsid, WorkflowClient.WORKFLOWTRANSITION_DELETE, WorkflowClient.WORKFLOWSTATE_REPLICATED_DEPRECATED_DELETED);
375         // Substract workflow states
376         updateItemLifeCycleState(testName, knownResourceId, itemCsid, WorkflowClient.WORKFLOWTRANSITION_UNREPLICATE, WorkflowClient.WORKFLOWSTATE_DEPRECATED_DELETED);
377         updateItemLifeCycleState(testName, knownResourceId, itemCsid, WorkflowClient.WORKFLOWTRANSITION_UNDELETE, WorkflowClient.WORKFLOWSTATE_DEPRECATED);
378         updateItemLifeCycleState(testName, knownResourceId, itemCsid, WorkflowClient.WORKFLOWTRANSITION_UNDEPRECATE, WorkflowClient.WORKFLOWSTATE_PROJECT);
379         // Add other workflow states
380         updateItemLifeCycleState(testName, knownResourceId, itemCsid, WorkflowClient.WORKFLOWTRANSITION_DELETE, WorkflowClient.WORKFLOWSTATE_DELETED);
381         updateItemLifeCycleState(testName, knownResourceId, itemCsid, WorkflowClient.WORKFLOWTRANSITION_REPLICATE, WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED);
382     }
383
384     
385     /**
386      * Verify that we can test synchronization with this authority.  Otherwise, we skip the test.
387      * @throws Exception 
388      */
389         private void assertSupportsSync() throws Exception {
390         //
391         // Test to see if the authority on our locally tenant supports sync
392         //
393         AuthorityClient client = (AuthorityClient) this.getClientInstance();
394         if (client.supportsSync() == false) {
395                 throw new SkipException(String.format("Skipped the test since this authority '%s' doesn't support synchronization.",
396                                 client.getServiceName()));
397         }
398         //
399         // Test to see if the test tenancy's authority supports synchronization.
400         // 
401         AuthorityClient sasClient = (AuthorityClient) this.getSASClientInstance();
402         if (sasClient.supportsSync() == false) {
403                 String tenantName = sasClient.getTenantName();
404                 throw new SkipException(String.format("Skipped the test since this authority '%s' doesn't support synchronization on the server's tenant '%s'.",
405                                 sasClient.getServiceName(), tenantName != null ? tenantName : "unknown"));
406         }
407     }
408         
409     /**
410      * Sync the local with the SAS
411      * @throws Exception 
412      */
413         @Test(dataProvider = "testName", dependsOnMethods = {"createSASItemList", "CRUDTests"})
414     public void syncWithSAS(String testName) throws Exception {
415         //
416         // First check to see if the authority supports synchronization.
417         //
418         assertSupportsSync();
419         
420         //
421         // Create an empty instance of the authority, so we can sync items with it.  We're
422         // using the short ID of the SAS authority.  The short ID of the local and the SAS will (must) be the same.
423         //
424         AuthorityClient client = (AuthorityClient) getClientInstance();
425         String localAuthorityId = null;
426         try {
427                         localAuthorityId = createResource(client, testName, knownSASAuthorityResourceShortId, false);
428                 } catch (Exception e) {
429                         Assert.assertNotNull(localAuthorityId);
430                 }
431
432         //
433         // Now we can try to sync the SAS authority with the local one we just created.
434         //
435         setupSync();
436         Response response = client.syncByName(knownSASAuthorityResourceShortId); // Notice we're using the Short ID (short ID is the same on the local and SAS)
437         try {
438                 int statusCode = response.getStatus();
439                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
440                         invalidStatusCodeMessage(testRequestType, statusCode));
441                 Assert.assertEquals(statusCode, testExpectedStatusCode);
442         } finally {
443                 response.close();
444         }
445         
446         //
447         // Check to see if the parent authority (local) is in the "Replicated" state.
448         //
449         setupRead();
450         response = client.readByName(knownSASAuthorityResourceShortId); // Notice we're using the Short ID (short ID is the same on the local and SAS)
451         try {
452                 int statusCode = response.getStatus();
453                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
454                         invalidStatusCodeMessage(testRequestType, statusCode));
455                 Assert.assertEquals(statusCode, testExpectedStatusCode);
456                         String workflowState = this.extractAuthorityWorkflowState(response);
457                         Assert.assertTrue(workflowState.contains(WorkflowClient.WORKFLOWSTATE_REPLICATED));  // After a sync, the parent should be in the "Replicated" state
458         } finally {
459                 response.close();
460         }
461     }
462     
463         @Test(dataProvider = "testName", dependsOnMethods = {"createSASAuthorityWithRelations", "CRUDTests"})
464     public void syncWithSASWithRelations(String testName) throws Exception {
465         //
466         // First check to see if the authority supports synchronization.
467         //
468         assertSupportsSync();
469                 
470         //
471         // Create an empty instance of the authority, so we can sync items with it.  We're
472         // using the short ID of the SAS authority.  The short ID of the local and the SAS will (must) be the same.
473         //
474         AuthorityClient client = (AuthorityClient) this.getClientInstance();
475         String localAuthorityId = null;
476         try {
477                         localAuthorityId = createResource(client, testName, knownSASAuthorityResourceWithRelationsShortId, false);
478                 } catch (Exception e) {
479                         Assert.assertNotNull(localAuthorityId);
480                 }
481
482         //
483         // Now we can try to sync the SAS authority with the local one we just created.
484         //
485         setupSync();
486         Response response = client.syncByName(knownSASAuthorityResourceWithRelationsShortId); // Notice we're using the Short ID (short ID is the same on the local and SAS)
487         try {
488                 int statusCode = response.getStatus();
489                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
490                         invalidStatusCodeMessage(testRequestType, statusCode));
491                 Assert.assertEquals(statusCode, testExpectedStatusCode);
492         } finally {
493                 response.close();
494         }
495         
496         //
497         // Check to see if the parent authority (local) is in the "Replicated" state.
498         //
499         setupRead();
500         response = client.readByName(knownSASAuthorityResourceWithRelationsShortId); // Notice we're using the Short ID (short ID is the same on the local and SAS)
501         try {
502                 int statusCode = response.getStatus();
503                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
504                         invalidStatusCodeMessage(testRequestType, statusCode));
505                 Assert.assertEquals(statusCode, testExpectedStatusCode);
506                         String workflowState = this.extractAuthorityWorkflowState(response);
507                         Assert.assertTrue(workflowState.contains(WorkflowClient.WORKFLOWSTATE_REPLICATED));  // After a sync, the parent should be in the "Replicated" state
508         } finally {
509                 response.close();
510         }
511     }
512     
513     /**
514      * Check to make sure the sync with the SAS returned the correct number of items as well as items
515      * with the correct short IDs.
516      * @throws Exception 
517      * 
518      */
519         @Test(dataProvider = "testName", dependsOnMethods = {"syncWithSAS", "CRUDTests"})
520     public void veryifySyncWithSAS(String testName) throws Exception {
521         //
522         // First check to see if we support sync.
523         //
524         assertSupportsSync();
525         
526         // Perform setup.
527         setupReadList();
528
529         // Submit the request to the service and store the response.
530         AuthorityClient client = (AuthorityClient) getClientInstance();
531         Response res = null;
532         res = client.readItemListForNamedAuthority(knownSASAuthorityResourceShortId, null, null);
533
534         try {
535                 int statusCode = res.getStatus();
536         
537                 // Check the status code of the response: does it match
538                 // the expected response(s)?
539                 if (logger.isDebugEnabled()) {
540                     logger.debug("  " + testName + ": status = " + statusCode);
541                 }
542                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
543                         invalidStatusCodeMessage(testRequestType, statusCode));
544                 Assert.assertEquals(statusCode, testExpectedStatusCode);
545         
546                 AbstractCommonList list = res.readEntity(AbstractCommonList.class);
547                 List<AbstractCommonList.ListItem> items = list.getListItem();
548                 int nItemsReturned = items.size();
549                 long nItemsTotal = list.getTotalItems();
550                 if (logger.isDebugEnabled()) {
551                     logger.debug("  " + testName + ": Expected "
552                             + nItemsToCreateInList + " items; got: " + nItemsReturned + " of: " + nItemsTotal);
553                 }
554                 Assert.assertEquals(nItemsTotal, SAS_ITEMLIST_SIZE);
555                 //
556                 // Verify that each of our local items has a corresponding remote item
557                 //
558                         for (AbstractCommonList.ListItem item : items) {
559                                 String shortId = AbstractCommonListUtils.ListItemGetElementValue(
560                                                 item, AuthorityClient.SHORT_IDENTIFIER);
561                                 Assert.assertTrue(knownSASItemIdentifiersList.contains(shortId)); // The local short ID should be in SAS list
562                                 
563                                 String workflowState = AbstractCommonListUtils.ListItemGetElementValue(
564                                                 item, CollectionSpaceClient.COLLECTIONSPACE_CORE_WORKFLOWSTATE);
565                                 Assert.assertTrue(workflowState.contains(WorkflowClient.WORKFLOWSTATE_REPLICATED)); // Workflow state must show up in a "replicated" state
566                                 
567                                 String refName = AbstractCommonListUtils.ListItemGetElementValue(
568                                                 item, AuthorityClient.REF_NAME);
569                                 Assert.assertTrue((refName != null), "Item refName is null or not set in the item list!");
570                                 String termDisplayName = AbstractCommonListUtils.ListItemGetElementValue(item,
571                                                 AuthorityClient.TERM_DISPLAY_NAME);
572                                 String vocabDisplayName = AbstractCommonListUtils.ListItemGetElementValue(item,
573                                                 AuthorityClient.VOCAB_DISPLAY_NAME);
574                                 // One of these names needs to be set.
575                                 Assert.assertTrue(!(termDisplayName == null && vocabDisplayName == null), "The item's display name is null or not set in the item list!");
576                         }
577                 
578                 if(logger.isTraceEnabled()){
579                         AbstractCommonListUtils.ListItemsInAbstractCommonList(list, logger, testName);
580                 }
581         } finally {
582                 res.close();
583         }
584     }
585     
586         @Test(dataProvider = "testName", dependsOnMethods = {"syncWithSASWithRelations", "CRUDTests"})
587     public void veryifySyncWithSASWithRelations(String testName) throws Exception {
588         //
589         // First check to see if we support sync.
590         //
591         assertSupportsSync();
592         
593         // Perform setup.
594         setupReadList();
595
596         // Submit the request to the service and store the response.
597         AuthorityClient client = (AuthorityClient) getClientInstance();
598         Response res = null;
599         res = client.readItemListForNamedAuthority(knownSASAuthorityResourceWithRelationsShortId, null, null);
600
601         try {
602                 int statusCode = res.getStatus();
603                 // Check the status code of the response: does it match
604                 // the expected response(s)?
605                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
606                         invalidStatusCodeMessage(testRequestType, statusCode));
607                 Assert.assertEquals(statusCode, testExpectedStatusCode);
608         
609                 AbstractCommonList list = res.readEntity(AbstractCommonList.class);
610                 long nItemsTotal = list.getTotalItems();
611                 Assert.assertEquals(nItemsTotal, knownSASItemIdentifiersWithRelationsList.size());
612                 //
613                 // Verify that each of our local items has a corresponding remote item
614                 //
615                 List<AbstractCommonList.ListItem> itemList = list.getListItem();
616                         for (AbstractCommonList.ListItem item : itemList) {
617                                 String shortId = AbstractCommonListUtils.ListItemGetElementValue(
618                                                 item, AuthorityClient.SHORT_IDENTIFIER);
619                                 Assert.assertTrue(knownSASItemIdentifiersWithRelationsList.contains(shortId)); // The local short ID should be in SAS list
620                                 
621                                 String workflowState = AbstractCommonListUtils.ListItemGetElementValue(
622                                                 item, CollectionSpaceClient.COLLECTIONSPACE_CORE_WORKFLOWSTATE);
623                                 Assert.assertTrue(workflowState.contains(WorkflowClient.WORKFLOWSTATE_REPLICATED)); // Workflow state must show up in a "replicated" state
624                                 
625                                 String refName = AbstractCommonListUtils.ListItemGetElementValue(
626                                                 item, AuthorityClient.REF_NAME);
627                                 Assert.assertTrue((refName != null), "Item refName is null or not set in the item list!");
628                                 String termDisplayName = AbstractCommonListUtils.ListItemGetElementValue(item,
629                                                 AuthorityClient.TERM_DISPLAY_NAME);
630                                 String vocabDisplayName = AbstractCommonListUtils.ListItemGetElementValue(item,
631                                                 AuthorityClient.VOCAB_DISPLAY_NAME);
632                                 // One of these names needs to be set.
633                                 Assert.assertTrue(!(termDisplayName == null && vocabDisplayName == null), "The item's display name is null or not set in the item list!");
634                         }               
635         } finally {
636                 res.close();
637         }
638         
639         //
640         // Verify the relationship hierarchy is correct.
641         //
642         AuthorityClient authorityClient = (AuthorityClient) getClientInstance();
643         ServiceDescription serviceDescription = authorityClient.getServiceDescription();
644         final String authorityItemDocumentType = serviceDescription == null ? "unknown" : serviceDescription.getSubresourceDocumentType();
645         
646         verifyBroaderRelationship(authorityClient, knownSASAuthorityResourceWithRelationsShortId, cityShortId, countryShortId, authorityItemDocumentType);
647         verifyBroaderRelationship(authorityClient, knownSASAuthorityResourceWithRelationsShortId, countryShortId, continentShortId, authorityItemDocumentType);
648     }
649     
650     /**
651      * Verifies a broader relationship exists between the subject and object.
652      * 
653      * @param authorityClient
654      * @param authorityShortId
655      * @param subjectShortId
656      * @param objectShortId
657      * @param authorityItemDocumentType
658      * @throws Exception 
659      */
660     private void verifyBroaderRelationship(AuthorityClient authorityClient, String authorityShortId, String subjectShortId, String objectShortId, String authorityItemDocumentType) throws Exception {
661         setupReadList();
662         RelationClient relationClient = new RelationClient();
663         Response res = relationClient.readList(getCsidFromShortId(authorityClient, authorityShortId, subjectShortId),
664                         authorityItemDocumentType,
665                         RelationshipType.HAS_BROADER.value(),
666                         getCsidFromShortId(authorityClient, authorityShortId, objectShortId),
667                         authorityItemDocumentType);
668         try {
669                 int statusCode = res.getStatus();
670                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
671                         invalidStatusCodeMessage(testRequestType, statusCode));
672                 Assert.assertEquals(statusCode, testExpectedStatusCode);
673                 
674                 RelationsCommonList list = (RelationsCommonList) res.readEntity(RelationsCommonList.class);
675                 Assert.assertEquals(list.getTotalItems(), 1); // Should be exactly one relationship
676                 RelationListItem relationListItem = list.getRelationListItem().get(0);
677                 //
678                 // Check the subject and object refnames to see if the contain the correct short identifiers
679                 //
680                 Assert.assertTrue(relationListItem.getSubject().getRefName().contains(subjectShortId)); // The subject refname should contain our known short ID
681                 Assert.assertTrue(relationListItem.getSubject().getRefName().contains(authorityShortId)); // The subject refname should contain our known short ID
682                 // Now check the object refname
683                 Assert.assertTrue(relationListItem.getObject().getRefName().contains(objectShortId)); // The object refname should contain our known short ID
684                 Assert.assertTrue(relationListItem.getObject().getRefName().contains(authorityShortId)); // The object refname should contain our known short ID
685         } finally {
686                 res.close();
687         }
688     }
689         
690     /**
691      * SAS - Create a new authority on the SAS server.
692      * @param testName
693      * @throws Exception 
694      */    
695         @Test(dataProvider = "testName", dependsOnMethods = {"createItem", "CRUDTests"})
696     public void createSASAuthority(String testName) throws Exception {
697         //
698         // First check to see if the authority supports synchronization.
699         //
700         assertSupportsSync();
701         
702         // Perform setup.
703         setupCreate();
704
705         try {
706                 String newID = createResource(getSASClientInstance(), testName, getSASAuthorityIdentifier(), true);
707                 knownSASAuthorityResourceId = newID;
708                 knownSASAuthorityResourceShortId = getShortId(getSASClientInstance(), knownSASAuthorityResourceId);
709             if (logger.isDebugEnabled()) {
710                 String.format("Created SAS authority '%s' with CSID=%s.", getSASAuthorityIdentifier(), newID);
711             }
712         } catch (Exception e) {
713                 logger.info(String.format("Failed to create SAS authority '%s'.", getSASAuthorityIdentifier()));
714         }
715     }
716     
717         @Test(dataProvider = "testName", dependsOnMethods = {"deleteLocalItemWithSync", "CRUDTests"})
718     public void createSASAuthorityWithRelations(String testName) throws Exception {
719         //
720         // First check to see if the authority supports synchronization.
721         //
722                 assertSupportsSync();
723                 
724         // Perform setup.
725         setupCreate();
726         //
727         // Create a new authority on the remote server
728         //
729         AuthorityClient client = (AuthorityClient) getClientInstance();
730         try {
731                 String newID = createResource(getSASClientInstance(), testName, getSASAuthorityWithRelationsIdentifier(), true);
732                 knownSASAuthorityResourceWithRelationsId = newID;
733                 knownSASAuthorityResourceWithRelationsShortId = getShortId(getSASClientInstance(), knownSASAuthorityResourceWithRelationsId);
734         } catch (Exception e) {
735                 logger.info(String.format("Failed to create SAS authority with relations '%s'.", getSASAuthorityWithRelationsIdentifier()));
736         }
737         //
738         // Add three items to the remote authority
739         //
740         continentShortId = "Continent" + System.currentTimeMillis() + Math.abs(random.nextInt()); // short ID needs to be unique
741         String continentCSID = createItemInAuthority(getSASClientInstance(), knownSASAuthorityResourceWithRelationsId, continentShortId);
742         knownSASItemIdentifiersWithRelationsList.add(continentShortId);
743         allSASResourceItemIdsCreated.put(this.getUrnIdentifier(continentShortId), getUrnIdentifier(getSASAuthorityWithRelationsIdentifier()));
744         
745         countryShortId = "Country" + System.currentTimeMillis() + Math.abs(random.nextInt()); // short ID needs to be unique
746         String countryCSID = createItemInAuthority(getSASClientInstance(), knownSASAuthorityResourceWithRelationsId, countryShortId);
747         knownSASItemIdentifiersWithRelationsList.add(countryShortId);
748         allSASResourceItemIdsCreated.put(this.getUrnIdentifier(countryShortId), getUrnIdentifier(getSASAuthorityWithRelationsIdentifier()));
749
750         cityShortId = "City" + System.currentTimeMillis() + Math.abs(random.nextInt()); // short ID needs to be unique
751         String cityCSID = createItemInAuthority(getSASClientInstance(), knownSASAuthorityResourceWithRelationsId, cityShortId);
752         knownSASItemIdentifiersWithRelationsList.add(cityShortId);
753         allSASResourceItemIdsCreated.put(this.getUrnIdentifier(cityShortId), getUrnIdentifier(getSASAuthorityWithRelationsIdentifier()));
754         //
755         // Create a set of hierarchical relationships between the items
756         //
757         ServiceDescription serviceDescription = client.getServiceDescription();
758         final String authorityItemDocumentType = serviceDescription == null ? "unknown" : serviceDescription.getSubresourceDocumentType();        
759         RelationClient relationClient = new RelationClient(CollectionSpaceClient.SAS_CLIENT_PROPERTIES_FILENAME); // Get a Relation service client to the SAS
760         
761         boolean success = false;
762         try {
763                         createBroaderRelationship(relationClient, cityCSID, countryCSID, authorityItemDocumentType);
764                         createBroaderRelationship(relationClient, countryCSID, continentCSID, authorityItemDocumentType);
765                         success = true;
766                 } catch (Exception e) {
767                         logger.error(e.getMessage());
768                 }
769
770         Assert.assertTrue(success);
771     }
772     
773     /**
774      * Creates a broader relationship record between the subject and the object
775      * @param relationClient
776      * @throws Exception 
777      */
778     private void createBroaderRelationship(RelationClient relationClient, String subjectCSID, String objectCSID, String docType) throws Exception {
779         RelationsCommon relationCommon = new RelationsCommon();
780         
781         relationCommon.setSubjectCsid(subjectCSID);
782         relationCommon.setSubjectDocumentType(docType);
783         relationCommon.setObjectCsid(objectCSID);
784         relationCommon.setObjectDocumentType(docType);
785         relationCommon.setRelationshipType(RelationshipType.HAS_BROADER.value());
786         relationCommon.setPredicateDisplayName(RelationshipType.HAS_BROADER.value());
787         
788         PoxPayloadOut payloadOut = relationClient.createRequestTypeInstance(relationCommon);
789         Response res = relationClient.create(payloadOut);
790         try {
791                 if (res.getStatus() == HttpStatus.SC_CREATED) {
792                         String relationCSID = extractId(res);
793                         allRelationResourceIdsCreated.add(relationCSID); // keep track of what we create so we can cleanup later
794                 } else {
795                         String errMsg = "Could not create Relationship.";
796                         logger.error(errMsg);
797                         throw new Exception(errMsg);
798                 }
799         } finally {
800                 res.close();
801         }
802     }
803
804     /**
805      * SAS - Create an item in the SAS authority on the SAS server.
806      * @param testName
807      * @throws Exception 
808      */
809         @Test(dataProvider = "testName", dependsOnMethods = {"createSASAuthority", "CRUDTests"})
810     public void createSASItemList(String testName) throws Exception {
811         //
812         // First check to see if the authority supports synchronization.
813         //
814         assertSupportsSync();
815         
816         // Perform setup for create.
817         setupCreate();
818         
819         for (int i = 0; i < SAS_ITEMLIST_SIZE; i++) {
820                 String shortId = "SassyActor" + System.currentTimeMillis() + Math.abs(random.nextInt()); // short ID needs to be unique
821                 String newID = createItemInAuthority(getSASClientInstance(), knownSASAuthorityResourceId, shortId);
822         
823                         // Store the ID returned from the first item resource created
824                 // for additional tests below.
825                 if (knownSASItemResourceId == null) {
826                         knownSASItemResourceId = newID;
827                     if (null != testName && logger.isDebugEnabled()) {
828                         logger.debug(testName + ": knownSASItemResourceId=" + knownSASItemResourceId);
829                     }
830                 }
831                 
832                 knownSASItemIdentifiersList.add(shortId);
833
834                 //
835                 // Keep track of the SAS authority items we create, so we can delete them from
836                 // the *local* authority after we perform a sync operation.  We need to keep track
837                 // of the URN (not the CSID) since the CSIDs will differ on the SAS vs local.
838                 //
839                 this.allSASResourceItemIdsCreated.put(this.getUrnIdentifier(shortId), getUrnIdentifier(knownSASAuthorityResourceShortId));
840         }
841         
842     }
843     
844     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
845                 dependsOnMethods = {"createItem"})
846     public void createItemList(String testName) throws Exception {
847         knownAuthorityWithItems = createResource(testName, READITEMS_SHORT_IDENTIFIER);
848         knownAuthorityWithItemsIdentifier = getShortId(knownAuthorityWithItems);
849         for (int j = 0; j < nItemsToCreateInList; j++) {
850                 createItemInAuthority((AuthorityClient) getClientInstance(), knownAuthorityWithItems, this.getTestAuthorityItemShortId(true));
851         }
852     }
853     
854         private String getShortId(AuthorityClient client, String authorityCsid) throws Exception {
855         String result = null;
856         
857         // Submit the request to the service and store the response.
858         Response res = client.read(authorityCsid);
859         try {
860                 int statusCode = res.getStatus();
861                 result = this.extractAuthorityShortId(res);
862         } finally {
863                 res.close();
864         }
865         
866         return result;
867     }
868     
869         private String getShortId(String authorityCsid) throws Exception {
870         AuthorityClient client = (AuthorityClient) getClientInstance();
871         return getShortId(client, authorityCsid);
872     }
873
874     /**
875      * Read by name.
876      *
877      * @param testName the test name
878      * @throws Exception the exception
879      */
880     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
881                 dependsOnMethods = {"CRUDTests"})
882     public void readByName(String testName) throws Exception {
883         // Perform setup.
884         setupRead();
885
886         // Submit the request to the service and store the response.
887         AuthorityClient client = (AuthorityClient) this.getClientInstance();
888         Response res = client.readByName(getKnowResourceIdentifier());
889         try {
890                 int statusCode = res.getStatus();
891         
892                 // Check the status code of the response: does it match
893                 // the expected response(s)?
894                 if (logger.isDebugEnabled()) {
895                     logger.debug(testName + ": status = " + statusCode);
896                 }
897                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
898                         invalidStatusCodeMessage(testRequestType, statusCode));
899                 Assert.assertEquals(statusCode, testExpectedStatusCode);
900                 
901                 AUTHORITY_COMMON_TYPE commonPart = extractCommonPartValue(res);
902                 Assert.assertNotNull(commonPart);
903         } finally {
904                 res.close();
905         }
906     }
907     
908     /**
909      * Extracts the common part item from a service's item payload.
910      * 
911      * @param res
912      * @return
913      * @throws Exception
914      */
915         public AUTHORITY_ITEM_TYPE extractItemCommonPartValue(Response res) throws Exception {
916                 AUTHORITY_ITEM_TYPE result = null;
917                 
918         AuthorityClient client = (AuthorityClient) getClientInstance();
919                 PayloadInputPart payloadInputPart = extractPart(res, client.getItemCommonPartName());
920                 if (payloadInputPart != null) {
921                         result = (AUTHORITY_ITEM_TYPE) payloadInputPart.getBody();
922                 }
923                 Assert.assertNotNull(result,
924                                 "Part or body of part " + client.getCommonPartName() + " was unexpectedly null.");
925                 
926                 return result;
927         }
928                 
929         
930     /**
931      * Extracts the short ID from a service request payload
932      * 
933      * @param res
934      * @return
935      * @throws Exception
936      */
937         protected String extractAuthorityShortId(Response res) throws Exception {
938                 String result = null;
939                 
940         PoxPayloadIn input = new PoxPayloadIn((String)res.readEntity(getEntityResponseType()));         
941                 Document document = input.getDOMDocument();
942                 result = XmlTools.getElementValue(document, "//" + AuthorityClient.SHORT_IDENTIFIER);
943
944                 return result;
945         }    
946         
947         protected String extractCsid(Response res) throws Exception {
948                 String result = null;
949                 
950         PoxPayloadIn input = new PoxPayloadIn((String)res.readEntity(getEntityResponseType()));         
951                 Document document = input.getDOMDocument();
952                 result = XmlTools.getElementValue(document, "//" + AuthorityClient.COLLECTIONSPACE_CORE_CSID);
953
954                 return result;
955         }    
956     
957     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
958                 dependsOnMethods = {"readItem"})
959     public void readItemNonExistent(String testName) throws Exception {
960         // Perform setup.
961         setupReadNonExistent();
962
963         // Submit the request to the service and store the response.
964         AuthorityClient client = (AuthorityClient) getClientInstance();
965         Response res = client.readItem(knownResourceId, NON_EXISTENT_ID);
966         try {
967                 int statusCode = res.getStatus();
968         
969                 // Check the status code of the response: does it match
970                 // the expected response(s)?
971                 if (logger.isDebugEnabled()) {
972                     logger.debug(testName + ": status = " + statusCode);
973                 }
974                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
975                         invalidStatusCodeMessage(testRequestType, statusCode));
976                 Assert.assertEquals(statusCode, testExpectedStatusCode);
977         } finally {
978                 res.close();
979         }
980     }
981         
982     @Test(dataProvider = "testName",
983                 dependsOnMethods = {"createItem"})
984     public void readItem(String testName) throws Exception {
985         // Perform setup.
986         setupRead();
987
988         // Submit the request to the service and store the response.
989         AuthorityClient client = (AuthorityClient) getClientInstance();
990         Response res = client.readItem(knownResourceId, knownItemResourceId);
991         try {
992                 int statusCode = res.getStatus();
993         
994                 // Check the status code of the response: does it match
995                 // the expected response(s)?
996                 if (logger.isDebugEnabled()) {
997                     logger.debug(testName + ": status = " + statusCode);
998                 }
999                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
1000                         invalidStatusCodeMessage(testRequestType, statusCode));
1001                 Assert.assertEquals(statusCode, testExpectedStatusCode);
1002         
1003                 AUTHORITY_ITEM_TYPE itemCommonPart = extractItemCommonPartValue(res);
1004                 Assert.assertNotNull(itemCommonPart);
1005                 Assert.assertEquals(client.getInAuthority(itemCommonPart), knownResourceId);
1006                 verifyReadItemInstance(itemCommonPart);
1007         } finally {
1008                 res.close();
1009         }
1010     }
1011     
1012     protected abstract void verifyReadItemInstance(AUTHORITY_ITEM_TYPE item) throws Exception;
1013         
1014     @Test(dataProvider = "testName",
1015                 dependsOnMethods = {"testItemSubmitRequest", "updateItem", "verifyIgnoredUpdateWithInAuthority"})    
1016     public void deleteItem(String testName) throws Exception {
1017         // Perform setup.
1018         setupDelete();
1019
1020         // Submit the request to the service and store the response.
1021         AuthorityClient client = (AuthorityClient) getClientInstance();
1022         Response res = client.deleteItem(knownResourceId, knownItemResourceId);
1023         int statusCode;
1024         try {
1025                 statusCode = res.getStatus();
1026         } finally {
1027                 res.close();
1028         }
1029
1030         // Check the status code of the response: does it match
1031         // the expected response(s)?
1032         if (logger.isDebugEnabled()) {
1033             logger.debug("delete: status = " + statusCode);
1034         }
1035         Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
1036                 invalidStatusCodeMessage(testRequestType, statusCode));
1037         Assert.assertEquals(statusCode, testExpectedStatusCode);
1038     }
1039     
1040     protected void readItemListInt(String vcsid, String shortId, String testName) throws Exception {
1041         // Perform setup.
1042         setupReadList();
1043
1044         // Submit the request to the service and store the response.
1045         AuthorityClient client = (AuthorityClient) getClientInstance();
1046         Response res = null;
1047         if (vcsid != null) {
1048             res = client.readItemList(vcsid, null, null);
1049         } else if (shortId != null) {
1050             res = client.readItemListForNamedAuthority(shortId, null, null);
1051         } else {
1052             Assert.fail("Internal Error: readItemList both vcsid and shortId are null!");
1053         }
1054         try {
1055                 int statusCode = res.getStatus();
1056         
1057                 // Check the status code of the response: does it match
1058                 // the expected response(s)?
1059                 if (logger.isDebugEnabled()) {
1060                     logger.debug("  " + testName + ": status = " + statusCode);
1061                 }
1062                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
1063                         invalidStatusCodeMessage(testRequestType, statusCode));
1064                 Assert.assertEquals(statusCode, testExpectedStatusCode);
1065         
1066                 AbstractCommonList list = res.readEntity(AbstractCommonList.class);
1067                 List<AbstractCommonList.ListItem> items = list.getListItem();
1068                 int nItemsReturned = items.size();
1069                 long nItemsTotal = list.getTotalItems();
1070                 if (logger.isDebugEnabled()) {
1071                     logger.debug("  " + testName + ": Expected "
1072                             + nItemsToCreateInList + " items; got: " + nItemsReturned + " of: " + nItemsTotal);
1073                 }
1074                 Assert.assertEquals(nItemsTotal, nItemsToCreateInList);
1075         
1076                         for (AbstractCommonList.ListItem item : items) {
1077                                 String refName = AbstractCommonListUtils.ListItemGetElementValue(
1078                                                 item, AuthorityClient.REF_NAME);
1079                                 Assert.assertTrue((refName != null), "Item refName is null or not set in the item list!");
1080                                 String termDisplayName = AbstractCommonListUtils.ListItemGetElementValue(item,
1081                                                 AuthorityClient.TERM_DISPLAY_NAME);
1082                                 String vocabDisplayName = AbstractCommonListUtils.ListItemGetElementValue(item,
1083                                                 AuthorityClient.VOCAB_DISPLAY_NAME);
1084                                 // One of these names needs to be set.
1085                                 Assert.assertTrue(!(termDisplayName == null && vocabDisplayName == null), "The item's display name is null or not set in the item list!");
1086                         }
1087                 
1088                 if(logger.isTraceEnabled()){
1089                         AbstractCommonListUtils.ListItemsInAbstractCommonList(list, logger, testName);
1090                 }
1091         } finally {
1092                 res.close();
1093         }
1094     }
1095     
1096     @Test(dataProvider = "testName", dependsOnMethods = {"createItemList"})
1097     public void readItemList(String testName) throws Exception {
1098         readItemListInt(knownAuthorityWithItems, null, testName);
1099     }
1100
1101     @Test(dataProvider = "testName", dependsOnMethods = {"readItemList"})
1102     public void readItemListByName(String testName) throws Exception {
1103         readItemListInt(null, knownAuthorityWithItemsIdentifier, testName);
1104     }
1105
1106     @Test(dataProvider = "testName",
1107                 dependsOnMethods = {"deleteItem"})
1108     public void deleteNonExistentItem(String testName) throws Exception {
1109         // Perform setup.
1110         setupDeleteNonExistent();
1111
1112         // Submit the request to the service and store the response.
1113         AuthorityClient client = (AuthorityClient) getClientInstance();
1114         Response res = client.deleteItem(knownResourceId, NON_EXISTENT_ID);
1115         int statusCode;
1116         try {
1117                 statusCode = res.getStatus();
1118         } finally {
1119                 res.close();
1120         }
1121
1122         // Check the status code of the response: does it match
1123         // the expected response(s)?
1124         if (logger.isDebugEnabled()) {
1125             logger.debug(testName + ": status = " + statusCode);
1126         }
1127         Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
1128                 invalidStatusCodeMessage(testRequestType, statusCode));
1129         Assert.assertEquals(statusCode, testExpectedStatusCode);
1130     }
1131     
1132     protected String getServicePathItemsComponent() {
1133         return AuthorityClient.ITEMS;
1134     }
1135     
1136         public PoxPayloadOut createItemRequestTypeInstance(AUTHORITY_ITEM_TYPE itemTypeInstance) throws Exception {
1137                 PoxPayloadOut result = null;
1138                 
1139         AuthorityClient client = (AuthorityClient) getClientInstance();
1140         PoxPayloadOut payloadOut = new PoxPayloadOut(this.getServicePathItemsComponent());
1141         payloadOut.addPart(client.getItemCommonPartName(), itemTypeInstance);
1142         result = payloadOut;
1143                 
1144                 return result;
1145         }
1146
1147         /**
1148          * Update an Authority item.
1149          * 
1150          * @param testName
1151          * @throws Exception
1152          */
1153     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
1154                 dependsOnMethods = {"readItem", "CRUDTests", "verifyIgnoredUpdateWithInAuthority"})
1155     public void updateItem(String testName) throws Exception {
1156         // Perform setup.
1157         setupUpdate();
1158         AUTHORITY_ITEM_TYPE theUpdate = null;
1159
1160         // Retrieve the contents of a resource to update.
1161         AuthorityClient client = (AuthorityClient)this.getClientInstance();
1162         Response res = client.readItem(knownResourceId, knownItemResourceId);
1163         try {
1164                 if (logger.isDebugEnabled()) {
1165                     logger.debug(testName + ": read status = " + res.getStatus());
1166                 }
1167                 Assert.assertEquals(res.getStatus(), testExpectedStatusCode);
1168         
1169                 if (logger.isDebugEnabled()) {
1170                     logger.debug("got Authority item to update with ID: "
1171                             + knownItemResourceId
1172                             + " in authority: " + knownResourceId);
1173                 }
1174                 AUTHORITY_ITEM_TYPE authorityItem = extractItemCommonPartValue(res);
1175                 Assert.assertNotNull(authorityItem);
1176
1177                 // Update the contents of this resource.
1178                 theUpdate = updateItemInstance(authorityItem);
1179                 if (logger.isDebugEnabled()) {
1180                     logger.debug("\n\nTo be updated fields: CSID = "  + knownItemResourceId + "\n"
1181                                 + objectAsXmlString(theUpdate));
1182                 }
1183         } finally {
1184                 res.close();
1185         }
1186
1187         // Submit the updated resource to the service and store the response.
1188         PoxPayloadOut output = this.createItemRequestTypeInstance(theUpdate);
1189         res = client.updateItem(knownResourceId, knownItemResourceId, output);
1190         try {
1191                 int statusCode = res.getStatus();
1192         
1193                 // Check the status code of the response: does it match the expected response(s)?
1194                 if (logger.isDebugEnabled()) {
1195                     logger.debug("updateItem: status = " + statusCode);
1196                 }
1197                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
1198                         invalidStatusCodeMessage(testRequestType, statusCode));
1199                 Assert.assertEquals(statusCode, testExpectedStatusCode);
1200         
1201                 // Retrieve the updated resource and verify that its contents exist.
1202                 AUTHORITY_ITEM_TYPE updatedVocabularyItem = extractItemCommonPartValue(res);
1203                 Assert.assertNotNull(updatedVocabularyItem);
1204
1205                 compareUpdatedItemInstances(theUpdate, updatedVocabularyItem);
1206         } finally {
1207                 res.close();
1208         }
1209     }
1210     
1211         @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
1212                 dependsOnMethods = {"updateLocalItemWithSync", "CRUDTests"})
1213     public void deleteLocalItemWithSync(String testName) throws Exception {
1214         final int itemIndexToDelete = 1;
1215         //
1216         // First check to see if we support sync.
1217         //
1218         assertSupportsSync();
1219         
1220         // Perform test setup for a DELETE.
1221         setupDelete();
1222
1223         // Delete an item from the SAS server
1224         AuthorityClient sasClient = (AuthorityClient) this.getSASClientInstance();
1225         Response res = sasClient.deleteNamedItemInNamedAuthority(knownSASAuthorityResourceShortId, knownSASItemIdentifiersList.get(itemIndexToDelete));
1226         try {
1227                 Assert.assertEquals(res.getStatus(), testExpectedStatusCode);   
1228         } finally {
1229                 res.close();
1230         }
1231         
1232         // Synchronize the local item's parent authority and verify the delete we just made
1233         // to the SAS takes place locally after the sync -i.e., the local item should be deleted as well.
1234         setupSync();
1235         AuthorityClient localClient = (AuthorityClient) this.getClientInstance();
1236         Response response = localClient.syncByName(knownSASAuthorityResourceShortId); // Notice we're using the Short ID (short ID is the same on the local and SAS)
1237         try {
1238                 int statusCode = response.getStatus();
1239                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode), invalidStatusCodeMessage(testRequestType, statusCode));
1240                 Assert.assertEquals(statusCode, testExpectedStatusCode);
1241         } finally {
1242                 response.close();
1243         }        
1244         
1245         // Verify that the local item has been deleted.
1246         setupReadNonExistent();
1247         res = localClient.readNamedItemInNamedAuthority(knownSASAuthorityResourceShortId, knownSASItemIdentifiersList.get(itemIndexToDelete));
1248         try {
1249                 Assert.assertEquals(res.getStatus(), testExpectedStatusCode);
1250                 knownSASItemIdentifiersList.remove(0); // remove it from our known set now that we've deleted it
1251         } finally {
1252                 res.close();
1253         }
1254     }
1255     
1256     /**
1257      * We create a new item on the SAS, perform a sync with the local authority, and verify the local authority contains a copy
1258      * of the SAS item. 
1259      */
1260         @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
1261                 dependsOnMethods = {"veryifySyncWithSAS", "CRUDTests"})
1262     public void updateLocalItemWithSync(String testName) throws Exception {
1263         //
1264         // First check to see if we support sync.
1265         //
1266         assertSupportsSync();
1267         
1268         // Perform setup.
1269         setupUpdate();
1270
1271         // Retrieve the contents of a shared authority item that we're going to update.
1272         AUTHORITY_ITEM_TYPE theUpdate = null;
1273         AUTHORITY_ITEM_TYPE sasAuthorityItem = null;
1274         AuthorityClient sasClient = (AuthorityClient) this.getSASClientInstance();
1275         Response res = sasClient.readNamedItemInNamedAuthority(knownSASAuthorityResourceShortId, knownSASItemIdentifiersList.get(0));
1276         try {
1277                 if (logger.isDebugEnabled()) {
1278                     logger.debug(testName + ": read status = " + res.getStatus());
1279                 }
1280                 Assert.assertEquals(res.getStatus(), testExpectedStatusCode);
1281         
1282                 sasAuthorityItem = extractItemCommonPartValue(res);  // This is a SAS authority item
1283                 Assert.assertNotNull(sasAuthorityItem);
1284         } finally {
1285                 res.close();
1286         }
1287
1288         // Update the contents of this authority item so we can post an UPDATE to the server
1289         theUpdate = updateItemInstance(sasAuthorityItem);
1290
1291         // Submit the updated authority item and check the response.
1292         PoxPayloadOut output = this.createItemRequestTypeInstance(theUpdate);
1293         res = sasClient.updateNamedItemInNamedAuthority(knownSASAuthorityResourceShortId, knownSASItemIdentifiersList.get(0), output);
1294         AUTHORITY_ITEM_TYPE updatedSASAuthorityItem = null;
1295         try {
1296                 int statusCode = res.getStatus();
1297         
1298                 // Check the status code of the response: does it match the expected response(s)?
1299                 if (logger.isDebugEnabled()) {
1300                     logger.debug("updateItem: status = " + statusCode);
1301                 }
1302                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
1303                         invalidStatusCodeMessage(testRequestType, statusCode));
1304                 Assert.assertEquals(statusCode, testExpectedStatusCode);
1305         
1306                 // Retrieve the updated authority item and verify that its contents exist.
1307                 updatedSASAuthorityItem = extractItemCommonPartValue(res);
1308                 Assert.assertNotNull(updatedSASAuthorityItem);
1309
1310                 compareUpdatedItemInstances(theUpdate, updatedSASAuthorityItem);
1311         } finally {
1312                 res.close();
1313         }
1314         
1315         // Synchronize the local item's parent authority and verify the update we just made
1316         // to the SAS item appears locally after the sync
1317         setupSync();
1318         AuthorityClient localClient = (AuthorityClient) this.getClientInstance();
1319         Response response = localClient.syncByName(knownSASAuthorityResourceShortId); // Notice we're using the Short ID (short ID is the same on the local and SAS)
1320         try {
1321                 int statusCode = response.getStatus();
1322                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode), invalidStatusCodeMessage(testRequestType, statusCode));
1323                 Assert.assertEquals(statusCode, testExpectedStatusCode);
1324         } finally {
1325                 response.close();
1326         }        
1327         
1328         setupRead();
1329         res = localClient.readNamedItemInNamedAuthority(knownSASAuthorityResourceShortId, knownSASItemIdentifiersList.get(0));
1330         try {
1331                 Assert.assertEquals(res.getStatus(), testExpectedStatusCode);
1332                 AUTHORITY_ITEM_TYPE syncedAuthorityItem = extractItemCommonPartValue(res);
1333                 Assert.assertNotNull(syncedAuthorityItem);
1334                 compareUpdatedItemInstances(syncedAuthorityItem, updatedSASAuthorityItem);
1335         } finally {
1336                 res.close();
1337         }
1338     }    
1339     
1340     protected abstract PoxPayloadOut createNonExistenceItemInstance(String commonPartName, String identifier);
1341     
1342     /* (non-Javadoc)
1343      * @see org.collectionspace.services.client.test.ServiceTest#updateNonExistent(java.lang.String)
1344      */
1345     @Test(dataProvider = "testName",
1346         dependsOnMethods = {"create", "update", "updateNonExistent"})
1347     public void updateNonExistentItem(String testName) throws Exception {
1348         // Perform setup.
1349         setupUpdateNonExistent();
1350
1351         // Submit the request to the service and store the response.
1352         // Note: The ID used in this 'create' call may be arbitrary.
1353         // The only relevant ID may be the one used in update(), below.
1354         AuthorityClient client = (AuthorityClient)this.getClientInstance();
1355         PoxPayloadOut multipart = createNonExistenceItemInstance(client.getItemCommonPartName(), NON_EXISTENT_ID);
1356         Response res = client.updateItem(knownResourceId, NON_EXISTENT_ID, multipart);
1357         try {
1358                 int statusCode = res.getStatus();
1359         
1360                 // Check the status code of the response: does it match
1361                 // the expected response(s)?
1362                 if (logger.isDebugEnabled()) {
1363                         logger.debug(testName + ": status = " + statusCode);
1364                 }
1365                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
1366                                 invalidStatusCodeMessage(testRequestType, statusCode));
1367                 Assert.assertEquals(statusCode, testExpectedStatusCode);
1368         } finally {
1369                 res.close();
1370         }
1371     }
1372         
1373     //
1374     // Methods to persuade TestNG to follow the correct test dependency path
1375     //
1376     
1377     @Test(dataProvider = "testName",
1378                 dependsOnMethods = {"createItem"})
1379     public void baseAuthorityTests(String testName) {
1380         // Do nothing.  Here just to setup a test dependency chain.
1381     }
1382     
1383     /*
1384      * For convenience and terseness, this test method is the base of the test execution dependency chain.  Other test methods may
1385      * refer to this method in their @Test annotation declarations.
1386      */
1387     @Override
1388     @Test(dataProvider = "testName",
1389                 dependsOnMethods = {
1390                         "org.collectionspace.services.client.test.AbstractServiceTestImpl.baseCRUDTests"})    
1391         public void CRUDTests(String testName) {
1392                 // TODO Auto-generated method stub
1393         }
1394         
1395     @Override
1396     public void cleanUp() throws Exception {
1397         String noTest = System.getProperty("noTestCleanup");
1398         if (Boolean.TRUE.toString().equalsIgnoreCase(noTest)) {
1399             if (logger.isDebugEnabled()) {
1400                 logger.debug("Skipping Cleanup phase ...");
1401             }
1402             return;
1403         }
1404         
1405         AuthorityClient client = (AuthorityClient) this.getClientInstance();
1406         String parentResourceId;
1407         String itemResourceId;
1408         //
1409         // Clean up all authority item resources.
1410         //
1411         for (Map.Entry<String, String> entry : allResourceItemIdsCreated.entrySet()) {
1412             itemResourceId = entry.getKey();
1413             parentResourceId = entry.getValue();
1414             Response response = client.deleteItem(parentResourceId, itemResourceId);
1415             try {
1416                 int status = response.getStatus();
1417                 if (status != Response.Status.OK.getStatusCode()) {
1418                         logger.debug(String.format("Could not deleted authority item '%s' in authority '%s'.",
1419                                         itemResourceId, parentResourceId));
1420                 }
1421             } finally {
1422                 response.close();
1423             }
1424         }
1425         //
1426         // Clean up authority items that were the result of a sync with the SAS
1427         // all the IDs are URN (not CSIDs).  The URNs work for the local items as well
1428         // as the SAS items.
1429         //
1430         for (Map.Entry<String, String> entry : allSASResourceItemIdsCreated.entrySet()) {
1431             itemResourceId = entry.getKey();
1432             parentResourceId = entry.getValue();
1433             // Note: Any non-success responses from the delete operation
1434             // below are ignored and not reported.
1435             client.deleteItem(parentResourceId, itemResourceId).close();
1436         }
1437         //
1438         // Clean up authority items on the SAS using the SAS client.
1439         //
1440         AuthorityClient sasClient = (AuthorityClient) this.getSASClientInstance();
1441         for (Map.Entry<String, String> entry : allSASResourceItemIdsCreated.entrySet()) {
1442             itemResourceId = entry.getKey();
1443             parentResourceId = entry.getValue();
1444             sasClient.deleteItem(parentResourceId, itemResourceId).close();
1445         }
1446         //
1447         // Finally, call out superclass's cleanUp method to deleted the local authorities
1448         //
1449         super.cleanUp();
1450         //
1451         // Call out superclass's cleanUp method to delete the SAS authorities
1452         //
1453         super.cleanUp(sasClient);
1454     }
1455     
1456         protected String getTestAuthorityItemShortId() {
1457                 return getTestAuthorityItemShortId(false);
1458         }
1459
1460         protected String getTestAuthorityItemShortId(boolean makeUnique) {
1461                 String result = TEST_SHORTID;
1462                 
1463                 if (makeUnique == true) {
1464                         result = result + System.currentTimeMillis() + Math.abs(random.nextInt());
1465                 }
1466                 
1467                 return result;
1468         }
1469         
1470     /**
1471      * Sets up create tests with empty entity body.
1472      */
1473     @Override
1474         protected void setupCreateWithEmptyEntityBody() {
1475         testExpectedStatusCode = STATUS_INTERNAL_SERVER_ERROR;
1476         testRequestType = ServiceRequestType.CREATE;
1477         testSetup(testExpectedStatusCode, testRequestType);
1478     }
1479         
1480     /**
1481      * Sets up create tests with malformed xml.
1482      */
1483     @Override
1484         protected void setupCreateWithMalformedXml() {
1485         testExpectedStatusCode = STATUS_INTERNAL_SERVER_ERROR;  // Malformed payload never gets past RESTEasy filter
1486         testRequestType = ServiceRequestType.CREATE;
1487         testSetup(testExpectedStatusCode, testRequestType);
1488     }
1489
1490     /**
1491      * Sets up create tests with wrong xml schema.
1492      */
1493     @Override
1494         protected void setupCreateWithWrongXmlSchema() {
1495         testExpectedStatusCode = STATUS_INTERNAL_SERVER_ERROR;  // Empty payload never gets past RESTEasy filter
1496         testRequestType = ServiceRequestType.CREATE;
1497         testSetup(testExpectedStatusCode, testRequestType);
1498     }    
1499     
1500 }