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