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