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