]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
7296efde086b494d9160cb3f8944083166c362d8
[tmp/jakarta-migration.git] /
1 package org.collectionspace.services.client.test;
2
3 import java.lang.reflect.Array;
4 import java.util.ArrayList;
5 import java.util.HashMap;
6 import java.util.List;
7 import java.util.Map;
8
9 import javax.ws.rs.core.Response;
10
11 import org.collectionspace.services.client.AbstractCommonListUtils;
12 import org.collectionspace.services.client.AuthorityClient;
13 import org.collectionspace.services.client.AuthorityClientImpl;
14 import org.collectionspace.services.client.AuthorityProxy;
15 import org.collectionspace.services.client.CollectionSpaceClient;
16 import org.collectionspace.services.client.PayloadInputPart;
17 import org.collectionspace.services.client.PayloadOutputPart;
18 import org.collectionspace.services.client.PoxPayloadIn;
19 import org.collectionspace.services.client.PoxPayloadOut;
20 import org.collectionspace.services.client.XmlTools;
21 import org.collectionspace.services.client.workflow.WorkflowClient;
22 import org.collectionspace.services.jaxb.AbstractCommonList;
23 import org.dom4j.Document;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26 import org.testng.Assert;
27 import org.testng.annotations.Test;
28
29 /**
30  * 
31  * @author remillet
32  *
33  * @param <AUTHORITY_COMMON_TYPE>
34  * @param <AUTHORITY_ITEM_TYPE>
35  * 
36  * All CRUD related authority test classes should extend this class.
37  * 
38  */
39 public abstract class AbstractAuthorityServiceTest<AUTHORITY_COMMON_TYPE, AUTHORITY_ITEM_TYPE> 
40         extends AbstractPoxServiceTestImpl<AbstractCommonList, AUTHORITY_COMMON_TYPE> {
41
42     private final Logger logger = LoggerFactory.getLogger(AbstractAuthorityServiceTest.class);
43         
44     protected String knownResourceShortIdentifer = null;
45         protected static final String READITEMS_SHORT_IDENTIFIER = "resourceWithItems" + random.nextInt(1000); 
46         protected String knownAuthorityWithItems = null;
47         protected String knownAuthorityWithItemsIdentifier = null;
48         
49         protected static final String SAS_IDENTIFIER = "SAS";
50
51         private static final int SAS_ITEMLIST_SIZE = 5; 
52         protected String knownSASAuthorityResourceId = null;
53         protected String knownSASAuthorityResourceIdentifier = null;
54         protected List<String> knownSASItemIdentifiersList = new ArrayList<String>();
55         protected String knownSASItemResourceId = null;
56         protected HashMap<String, String> allSASResourceItemIdsCreated = new HashMap<String, String>(); /* itemURN, parentURN */;
57
58         protected String knownResourceRefName = null;
59     protected String knownItemResourceId = null;
60     protected String knownItemResourceShortIdentifer = null;    
61     protected int nItemsToCreateInList = 5;
62     protected String TEST_SHORTID = "johnWayneActor";
63
64     /*
65      * Abstract methods that subclasses must override/implement
66      */
67     
68     /**
69      * 
70      * @param testName
71      */
72     public abstract void authorityTests(String testName);
73         
74         /**
75          * 
76          * @param client
77          * @param vcsid
78          * @return
79          */
80         abstract protected String createItemInAuthority(AuthorityClient client, String vcsid, String shortId);
81         
82     
83     /**
84      * 
85      * @param authorityItem
86      * @return
87      */
88     protected abstract AUTHORITY_ITEM_TYPE updateItemInstance(final AUTHORITY_ITEM_TYPE authorityItem);    
89     
90     /**
91      * 
92      * @param original
93      * @param updated
94      * @throws Exception
95      */
96     protected abstract void compareUpdatedItemInstances(AUTHORITY_ITEM_TYPE original,
97                 AUTHORITY_ITEM_TYPE updated,
98                 boolean compareRevNumbers) throws Exception;
99     
100     /**
101      * 
102      * @param original
103      * @param updated
104      * @throws Exception
105      */
106     protected void compareUpdatedItemInstances(AUTHORITY_ITEM_TYPE original,
107                 AUTHORITY_ITEM_TYPE updated) throws Exception {
108         compareUpdatedItemInstances(original, updated, false);
109     }
110     
111     /**
112      * 
113      * @param id
114      * @param shortIdentifer
115      */
116     protected void setKnownItemResource(String id, String shortIdentifer ) {
117         knownItemResourceId = id;
118         knownItemResourceShortIdentifer = shortIdentifer;
119     }
120
121     /**
122      * 
123      * @param id
124      * @param shortIdentifer
125      * @param refName
126      */
127     protected void setKnownResource(String id, String shortIdentifer,
128             String refName) {
129         knownResourceId = id;
130         knownResourceShortIdentifer = shortIdentifer;
131         knownResourceRefName = refName;
132     }
133
134     /**
135      * 
136      * @return
137      */
138         protected String getSASAuthorityIdentifier() {
139                 // TODO Auto-generated method stub
140                 return this.getKnowResourceIdentifier() + SAS_IDENTIFIER;
141         }
142     
143         /**
144          * 
145          * @param shortId
146          * @return
147          */
148         protected String getUrnIdentifier(String shortId) {
149                 return String.format("urn:cspace:name(%s)", shortId);
150         }
151         
152     /**
153      * Sets up create tests.
154      */
155     protected void setupSync() {
156         testExpectedStatusCode = this.STATUS_OK;
157         testRequestType = ServiceRequestType.SYNC;
158         testSetup(testExpectedStatusCode, testRequestType);
159     }
160     
161     /**
162      * Gets a client to the SAS (Shared Authority Server)
163      *
164      * @return the client
165      */
166     protected AuthorityClient getSASClientInstance() {
167         return (AuthorityClient) this.getClientInstance(CollectionSpaceClient.SAS_CLIENT_PROPERTIES_FILENAME);
168     }
169
170     /**
171      * Returns the root URL for a service.
172      *
173      * This URL consists of a base URL for all services, followed by
174      * a path component for the owning vocabulary, followed by the 
175      * path component for the items.
176      *
177      * @return The root URL for a service.
178      */
179     protected String getItemServiceRootURL(String parentResourceIdentifier) {
180         return getResourceURL(parentResourceIdentifier) + "/" + getServicePathItemsComponent();
181     }
182
183     /**
184      * Returns the URL of a specific resource managed by a service, and
185      * designated by an identifier (such as a universally unique ID, or UUID).
186      *
187      * @param  resourceIdentifier  An identifier (such as a UUID) for a resource.
188      *
189      * @return The URL of a specific resource managed by a service.
190      */
191     protected String getItemResourceURL(String parentResourceIdentifier, String resourceIdentifier) {
192         return getItemServiceRootURL(parentResourceIdentifier) + "/" + resourceIdentifier;
193     }
194         
195     /**
196      * For authorities we override this method so we can save the shortid.
197      */
198     @Override
199     protected String createWithIdentifier(String testName, String identifier) throws Exception {
200         String csid = createResource(testName, identifier);
201         // Store the ID returned from the first resource created
202         // for additional tests below.
203         if (getKnowResourceId() == null) {
204                 setKnownResource(csid, identifier /*shortId*/, null /*refname*/ );
205             if (logger.isDebugEnabled()) {
206                 logger.debug(testName + ": Setting knownResourceId=" + getKnowResourceId());
207             }
208         }
209         
210         return identifier;
211     }    
212     
213     @Test(dependsOnMethods = {"readItem", "CRUDTests"})
214     public void testItemSubmitRequest() {
215
216         // Expected status code: 200 OK
217         final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
218
219         // Submit the request to the service and store the response.
220         String method = ServiceRequestType.READ.httpMethodName();
221         String url = getItemResourceURL(knownResourceId, knownItemResourceId);
222         int statusCode = submitRequest(method, url);
223
224         // Check the status code of the response: does it match
225         // the expected response(s)?
226         if (logger.isDebugEnabled()) {
227             logger.debug("testItemSubmitRequest: url=" + url
228                     + " status=" + statusCode);
229         }
230         Assert.assertEquals(statusCode, EXPECTED_STATUS);
231     }    
232
233     
234     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
235         dependsOnMethods = {"readItem"})
236     public void verifyIgnoredUpdateWithInAuthority(String testName) throws Exception {
237         // Perform setup.
238         setupUpdate();
239
240         // Submit the request to the service and store the response.
241         AuthorityClient client = (AuthorityClient)this.getClientInstance();
242         Response res = client.readItem(knownResourceId, knownItemResourceId);
243         AUTHORITY_ITEM_TYPE vitem = null;
244         try {
245                 int statusCode = res.getStatus();
246         
247                 // Check the status code of the response: does it match
248                 // the expected response(s)?
249                 if (logger.isDebugEnabled()) {
250                         logger.debug(testName + " read authority:" + knownResourceId + "/Item:"
251                                         + knownItemResourceId + " status = " + statusCode);
252                 }
253                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
254                                 invalidStatusCodeMessage(testRequestType, statusCode));
255                 Assert.assertEquals(statusCode, Response.Status.OK.getStatusCode());
256         
257                 vitem = extractItemCommonPartValue(res);
258                 Assert.assertNotNull(vitem);
259                 // Try to Update with new parent vocab (use self, for test).
260                 Assert.assertEquals(client.getInAuthority(vitem), knownResourceId,
261                                 "VocabularyItem inAuthority does not match knownResourceId.");
262                 client.setInAuthority(vitem, knownItemResourceId);
263
264         } finally {
265                 res.close();
266         }
267         
268         // Submit the updated resource to the service and store the response.
269         PoxPayloadOut output = this.createItemRequestTypeInstance(vitem);
270         res = client.updateItem(knownResourceId, knownItemResourceId, output);
271         try {
272                 int statusCode = res.getStatus();
273         
274                 // Check the status code of the response: does it match the expected response(s)?
275                 if (logger.isDebugEnabled()) {
276                         logger.debug(testName + ": status = " + statusCode);
277                 }
278                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
279                                 invalidStatusCodeMessage(testRequestType, statusCode));
280                 Assert.assertEquals(statusCode, testExpectedStatusCode);
281         } finally {
282                 res.close();
283         }
284         
285         res = client.readItem(knownResourceId, knownItemResourceId);
286         try {
287                 // Retrieve the updated resource and verify that the parent did not change
288                 AUTHORITY_ITEM_TYPE updatedVocabularyItem = extractItemCommonPartValue(res);
289                 Assert.assertNotNull(updatedVocabularyItem);
290         
291                 // Verify that the updated resource received the correct data.
292                 Assert.assertEquals(client.getInAuthority(updatedVocabularyItem),
293                                 knownResourceId,
294                                 "VocabularyItem allowed update to the parent (inAuthority).");
295         } finally {
296                 res.close();
297         }
298     }
299     
300     @Test(dataProvider = "testName", dependsOnMethods = {"CRUDTests"})
301     public void createItem(String testName) {
302         // Perform setup.
303         setupCreate();
304
305         String newID = createItemInAuthority((AuthorityClient) getClientInstance(), knownResourceId, getTestAuthorityItemShortId());
306
307         // Store the ID returned from the first item resource created
308         // for additional tests below.
309         if (knownItemResourceId == null) {
310             knownItemResourceId = newID;
311             if (null != testName && logger.isDebugEnabled()) {
312                 logger.debug(testName + ": knownItemResourceId=" + knownItemResourceId);
313             }
314         }
315     }
316         
317     /**
318      * Sync the local with the SAS
319      * @throws Exception 
320      */
321     @Test(dataProvider = "testName", dependsOnMethods = {"createSASItemList", "CRUDTests"})
322     public void syncWithSAS(String testName) throws Exception {
323         //
324         // First check to see if the authority supports synchronization.
325         //
326         AuthorityClient client = (AuthorityClient) this.getClientInstance();
327         if (client.supportsSync() == false) {
328                 return; // Exit the test since this authority doesn't support synchronization
329         }
330         
331         //
332         // Create an empty instance of the authority, so we can sync items with it.  We're
333         // using the short ID of the SAS authority.  The short ID of the local and the SAS will (must) be the same.
334         //
335         String localAuthorityId = null;
336         try {
337                         localAuthorityId = createResource(client, testName, knownSASAuthorityResourceIdentifier, false);
338                 } catch (Exception e) {
339                         Assert.assertNotNull(localAuthorityId);
340                 }
341
342         //
343         // Now we can try to sync the SAS authority with the local one we just created.
344         //
345         setupSync();
346         Response response = client.syncByName(knownSASAuthorityResourceIdentifier); // Notice we're using the Short ID (short ID is the same on the local and SAS)
347         try {
348                 int statusCode = response.getStatus();
349                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
350                         invalidStatusCodeMessage(testRequestType, statusCode));
351                 Assert.assertEquals(statusCode, testExpectedStatusCode);
352         } finally {
353                 response.close();
354         }
355         
356         //
357         // Check to see if the parent authority (local) is in the "Replicated" state.
358         //
359         setupRead();
360         response = client.readByName(knownSASAuthorityResourceIdentifier); // Notice we're using the Short ID (short ID is the same on the local and SAS)
361         try {
362                 int statusCode = response.getStatus();
363                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
364                         invalidStatusCodeMessage(testRequestType, statusCode));
365                 Assert.assertEquals(statusCode, testExpectedStatusCode);
366                         String workflowState = this.extractAuthorityWorkflowState(response);
367                         Assert.assertTrue(workflowState.contains(WorkflowClient.WORKFLOWSTATE_REPLICATED));  // After a sync, the parent should be in the "Replicated" state
368         } finally {
369                 response.close();
370         }        
371         
372     }
373     
374     /**
375      * Check to make sure the sync with the SAS returned the correct number of items as well as items
376      * with the correct short IDs.
377      * 
378      */
379     @Test(dataProvider = "testName", dependsOnMethods = {"syncWithSAS", "CRUDTests"})
380     public void veryifySyncWithSAS(String testName) {
381         // Perform setup.
382         setupReadList();
383
384         // Submit the request to the service and store the response.
385         AuthorityClient client = (AuthorityClient) getClientInstance();
386         Response res = null;
387         res = client.readItemListForNamedAuthority(knownSASAuthorityResourceIdentifier, null, null);
388
389         try {
390                 int statusCode = res.getStatus();
391         
392                 // Check the status code of the response: does it match
393                 // the expected response(s)?
394                 if (logger.isDebugEnabled()) {
395                     logger.debug("  " + testName + ": status = " + statusCode);
396                 }
397                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
398                         invalidStatusCodeMessage(testRequestType, statusCode));
399                 Assert.assertEquals(statusCode, testExpectedStatusCode);
400         
401                 AbstractCommonList list = res.readEntity(AbstractCommonList.class);
402                 List<AbstractCommonList.ListItem> items = list.getListItem();
403                 int nItemsReturned = items.size();
404                 long nItemsTotal = list.getTotalItems();
405                 if (logger.isDebugEnabled()) {
406                     logger.debug("  " + testName + ": Expected "
407                             + nItemsToCreateInList + " items; got: " + nItemsReturned + " of: " + nItemsTotal);
408                 }
409                 Assert.assertEquals(nItemsTotal, SAS_ITEMLIST_SIZE);
410         
411                         for (AbstractCommonList.ListItem item : items) {
412                                 String shortId = AbstractCommonListUtils.ListItemGetElementValue(
413                                                 item, AuthorityClient.SHORT_IDENTIFIER);
414                                 Assert.assertTrue(knownSASItemIdentifiersList.contains(shortId)); // The local short ID should be in SAS list
415                                 
416                                 String workflowState = AbstractCommonListUtils.ListItemGetElementValue(
417                                                 item, CollectionSpaceClient.COLLECTIONSPACE_CORE_WORKFLOWSTATE);
418                                 Assert.assertTrue(workflowState.contains(WorkflowClient.WORKFLOWSTATE_REPLICATED)); // Workflow state must show up in a "replicated" state
419                                 
420                                 String refName = AbstractCommonListUtils.ListItemGetElementValue(
421                                                 item, AuthorityClient.REF_NAME);
422                                 Assert.assertTrue((refName != null), "Item refName is null or not set in the item list!");
423                                 String termDisplayName = AbstractCommonListUtils.ListItemGetElementValue(item,
424                                                 AuthorityClient.TERM_DISPLAY_NAME);
425                                 String vocabDisplayName = AbstractCommonListUtils.ListItemGetElementValue(item,
426                                                 AuthorityClient.VOCAB_DISPLAY_NAME);
427                                 // One of these names needs to be set.
428                                 Assert.assertTrue(!(termDisplayName == null && vocabDisplayName == null), "The item's display name is null or not set in the item list!");
429                         }
430                 
431                 if(logger.isTraceEnabled()){
432                         AbstractCommonListUtils.ListItemsInAbstractCommonList(list, logger, testName);
433                 }
434         } finally {
435                 res.close();
436         }
437     }
438         
439     /**
440      * SAS - Create a new authority on the SAS server.
441      * @param testName
442      */    
443     @Test(dataProvider = "testName", dependsOnMethods = {"createItem", "CRUDTests"})
444     public void createSASAuthority(String testName) {
445         //
446         // First check to see if the authority supports synchronization.
447         //
448         AuthorityClient client = (AuthorityClient) this.getClientInstance();
449         if (client.supportsSync() == false) {
450                 return; // Exit the test since this authority doesn't support synchronization
451         }
452         
453         // Perform setup.
454         setupCreate();
455
456         try {
457                 String newID = createResource(getSASClientInstance(), testName, getSASAuthorityIdentifier(), true);
458                 knownSASAuthorityResourceId = newID;
459                 knownSASAuthorityResourceIdentifier = getShortId(getSASClientInstance(), knownSASAuthorityResourceId);
460             if (logger.isDebugEnabled()) {
461                 String.format("Created SAS authority '%s' with CSID=%s.", getSASAuthorityIdentifier(), newID);
462             }
463         } catch (Exception e) {
464                 logger.info(String.format("Failed to create SAS authority '%s'.", getSASAuthorityIdentifier()));
465         }
466     }
467
468     /**
469      * SAS - Create an item in the SAS authority on the SAS server.
470      * @param testName
471      */
472     @Test(dataProvider = "testName", dependsOnMethods = {"createSASAuthority", "CRUDTests"})
473     public void createSASItemList(String testName) {
474         //
475         // First check to see if the authority supports synchronization.
476         //
477         AuthorityClient client = (AuthorityClient) this.getClientInstance();
478         if (client.supportsSync() == false) {
479                 return; // Exit the test since this authority doesn't support synchronization
480         }
481         
482         // Perform setup.
483         setupCreate();
484
485         for (int i = 0; i < SAS_ITEMLIST_SIZE; i++) {
486                 String shortId = "SassyActor" + System.currentTimeMillis() + Math.abs(random.nextInt()); // short ID needs to be unique
487                 String newID = createItemInAuthority(getSASClientInstance(), knownSASAuthorityResourceId, shortId);
488         
489                         // Store the ID returned from the first item resource created
490                 // for additional tests below.
491                 if (knownSASItemResourceId == null) {
492                         knownSASItemResourceId = newID;
493                     if (null != testName && logger.isDebugEnabled()) {
494                         logger.debug(testName + ": knownSASItemResourceId=" + knownSASItemResourceId);
495                     }
496                 }
497                 
498                 knownSASItemIdentifiersList.add(shortId);
499
500                 //
501                 // Keep track of the SAS authority items we create, so we can delete them from
502                 // the *local* authority after we perform a sync operation.  We need to keep track
503                 // of the URN (not the CSID) since the CSIDs will differ on the SAS vs local.
504                 //
505                 this.allSASResourceItemIdsCreated.put(this.getUrnIdentifier(shortId), getUrnIdentifier(getSASAuthorityIdentifier()));
506         }
507         
508     }
509     
510     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
511                 dependsOnMethods = {"createItem"})
512     public void createItemList(String testName) throws Exception {
513         knownAuthorityWithItems = createResource(testName, READITEMS_SHORT_IDENTIFIER);
514         knownAuthorityWithItemsIdentifier = getShortId(knownAuthorityWithItems);
515         for (int j = 0; j < nItemsToCreateInList; j++) {
516                 createItemInAuthority((AuthorityClient) getClientInstance(), knownAuthorityWithItems, this.getTestAuthorityItemShortId(true));
517         }
518     }
519     
520     private String getShortId(AuthorityClient client, String authorityCsid) throws Exception {
521         String result = null;
522         
523         // Submit the request to the service and store the response.
524         Response res = client.read(authorityCsid);
525         try {
526                 int statusCode = res.getStatus();
527                 result = this.extractAuthorityShortId(res);
528         } finally {
529                 res.close();
530         }
531         
532         return result;
533     }
534     
535     private String getShortId(String authorityCsid) throws Exception {
536         AuthorityClient client = (AuthorityClient) getClientInstance();
537         return getShortId(client, authorityCsid);
538     }
539
540     /**
541      * Read by name.
542      *
543      * @param testName the test name
544      * @throws Exception the exception
545      */
546     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
547                 dependsOnMethods = {"CRUDTests"})
548     public void readByName(String testName) throws Exception {
549         // Perform setup.
550         setupRead();
551
552         // Submit the request to the service and store the response.
553         AuthorityClient client = (AuthorityClient) this.getClientInstance();
554         Response res = client.readByName(getKnowResourceIdentifier());
555         try {
556                 int statusCode = res.getStatus();
557         
558                 // Check the status code of the response: does it match
559                 // the expected response(s)?
560                 if (logger.isDebugEnabled()) {
561                     logger.debug(testName + ": status = " + statusCode);
562                 }
563                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
564                         invalidStatusCodeMessage(testRequestType, statusCode));
565                 Assert.assertEquals(statusCode, testExpectedStatusCode);
566                 
567                 AUTHORITY_COMMON_TYPE commonPart = extractCommonPartValue(res);
568                 Assert.assertNotNull(commonPart);
569         } finally {
570                 res.close();
571         }
572     }
573     
574     /**
575      * Extracts the common part item from a service's item payload.
576      * 
577      * @param res
578      * @return
579      * @throws Exception
580      */
581         public AUTHORITY_ITEM_TYPE extractItemCommonPartValue(Response res) throws Exception {
582                 AUTHORITY_ITEM_TYPE result = null;
583                 
584         AuthorityClient client = (AuthorityClient) getClientInstance();
585                 PayloadInputPart payloadInputPart = extractPart(res, client.getItemCommonPartName());
586                 if (payloadInputPart != null) {
587                         result = (AUTHORITY_ITEM_TYPE) payloadInputPart.getBody();
588                 }
589                 Assert.assertNotNull(result,
590                                 "Part or body of part " + client.getCommonPartName() + " was unexpectedly null.");
591                 
592                 return result;
593         }
594                 
595         
596     /**
597      * Extracts the short ID from a service request payload
598      * 
599      * @param res
600      * @return
601      * @throws Exception
602      */
603         protected String extractAuthorityShortId(Response res) throws Exception {
604                 String result = null;
605                 
606         PoxPayloadIn input = new PoxPayloadIn((String)res.readEntity(getEntityResponseType()));         
607                 Document document = input.getDOMDocument();
608                 result = XmlTools.getElementValue(document, "//" + AuthorityClient.SHORT_IDENTIFIER);
609
610                 return result;
611         }    
612         
613     
614     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
615                 dependsOnMethods = {"readItem"})
616     public void readItemNonExistent(String testName) {
617         // Perform setup.
618         setupReadNonExistent();
619
620         // Submit the request to the service and store the response.
621         AuthorityClient client = (AuthorityClient) getClientInstance();
622         Response res = client.readItem(knownResourceId, NON_EXISTENT_ID);
623         try {
624                 int statusCode = res.getStatus();
625         
626                 // Check the status code of the response: does it match
627                 // the expected response(s)?
628                 if (logger.isDebugEnabled()) {
629                     logger.debug(testName + ": status = " + statusCode);
630                 }
631                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
632                         invalidStatusCodeMessage(testRequestType, statusCode));
633                 Assert.assertEquals(statusCode, testExpectedStatusCode);
634         } finally {
635                 res.close();
636         }
637     }
638         
639     @Test(dataProvider = "testName",
640                 dependsOnMethods = {"createItem"})
641     public void readItem(String testName) throws Exception {
642         // Perform setup.
643         setupRead();
644
645         // Submit the request to the service and store the response.
646         AuthorityClient client = (AuthorityClient) getClientInstance();
647         Response res = client.readItem(knownResourceId, knownItemResourceId);
648         try {
649                 int statusCode = res.getStatus();
650         
651                 // Check the status code of the response: does it match
652                 // the expected response(s)?
653                 if (logger.isDebugEnabled()) {
654                     logger.debug(testName + ": status = " + statusCode);
655                 }
656                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
657                         invalidStatusCodeMessage(testRequestType, statusCode));
658                 Assert.assertEquals(statusCode, testExpectedStatusCode);
659         
660                 AUTHORITY_ITEM_TYPE itemCommonPart = extractItemCommonPartValue(res);
661                 Assert.assertNotNull(itemCommonPart);
662                 Assert.assertEquals(client.getInAuthority(itemCommonPart), knownResourceId);
663                 verifyReadItemInstance(itemCommonPart);
664         } finally {
665                 res.close();
666         }
667     }
668     
669     protected abstract void verifyReadItemInstance(AUTHORITY_ITEM_TYPE item) throws Exception;
670         
671     @Test(dataProvider = "testName",
672                 dependsOnMethods = {"testItemSubmitRequest", "updateItem", "verifyIgnoredUpdateWithInAuthority"})    
673     public void deleteItem(String testName) throws Exception {
674         // Perform setup.
675         setupDelete();
676
677         // Submit the request to the service and store the response.
678         AuthorityClient client = (AuthorityClient) getClientInstance();
679         Response res = client.deleteItem(knownResourceId, knownItemResourceId);
680         int statusCode;
681         try {
682                 statusCode = res.getStatus();
683         } finally {
684                 res.close();
685         }
686
687         // Check the status code of the response: does it match
688         // the expected response(s)?
689         if (logger.isDebugEnabled()) {
690             logger.debug("delete: status = " + statusCode);
691         }
692         Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
693                 invalidStatusCodeMessage(testRequestType, statusCode));
694         Assert.assertEquals(statusCode, testExpectedStatusCode);
695     }
696     
697     protected void readItemListInt(String vcsid, String shortId, String testName) {
698         // Perform setup.
699         setupReadList();
700
701         // Submit the request to the service and store the response.
702         AuthorityClient client = (AuthorityClient) getClientInstance();
703         Response res = null;
704         if (vcsid != null) {
705             res = client.readItemList(vcsid, null, null);
706         } else if (shortId != null) {
707             res = client.readItemListForNamedAuthority(shortId, null, null);
708         } else {
709             Assert.fail("Internal Error: readItemList both vcsid and shortId are null!");
710         }
711         try {
712                 int statusCode = res.getStatus();
713         
714                 // Check the status code of the response: does it match
715                 // the expected response(s)?
716                 if (logger.isDebugEnabled()) {
717                     logger.debug("  " + testName + ": status = " + statusCode);
718                 }
719                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
720                         invalidStatusCodeMessage(testRequestType, statusCode));
721                 Assert.assertEquals(statusCode, testExpectedStatusCode);
722         
723                 AbstractCommonList list = res.readEntity(AbstractCommonList.class);
724                 List<AbstractCommonList.ListItem> items = list.getListItem();
725                 int nItemsReturned = items.size();
726                 long nItemsTotal = list.getTotalItems();
727                 if (logger.isDebugEnabled()) {
728                     logger.debug("  " + testName + ": Expected "
729                             + nItemsToCreateInList + " items; got: " + nItemsReturned + " of: " + nItemsTotal);
730                 }
731                 Assert.assertEquals(nItemsTotal, nItemsToCreateInList);
732         
733                         for (AbstractCommonList.ListItem item : items) {
734                                 String refName = AbstractCommonListUtils.ListItemGetElementValue(
735                                                 item, AuthorityClient.REF_NAME);
736                                 Assert.assertTrue((refName != null), "Item refName is null or not set in the item list!");
737                                 String termDisplayName = AbstractCommonListUtils.ListItemGetElementValue(item,
738                                                 AuthorityClient.TERM_DISPLAY_NAME);
739                                 String vocabDisplayName = AbstractCommonListUtils.ListItemGetElementValue(item,
740                                                 AuthorityClient.VOCAB_DISPLAY_NAME);
741                                 // One of these names needs to be set.
742                                 Assert.assertTrue(!(termDisplayName == null && vocabDisplayName == null), "The item's display name is null or not set in the item list!");
743                         }
744                 
745                 if(logger.isTraceEnabled()){
746                         AbstractCommonListUtils.ListItemsInAbstractCommonList(list, logger, testName);
747                 }
748         } finally {
749                 res.close();
750         }
751     }
752     
753     @Test(dataProvider = "testName", dependsOnMethods = {"createItemList"})
754     public void readItemList(String testName) {
755         readItemListInt(knownAuthorityWithItems, null, testName);
756     }
757
758     @Test(dataProvider = "testName", dependsOnMethods = {"readItemList"})
759     public void readItemListByName(String testName) {
760         readItemListInt(null, knownAuthorityWithItemsIdentifier, testName);
761     }
762
763     @Test(dataProvider = "testName",
764                 dependsOnMethods = {"deleteItem"})
765     public void deleteNonExistentItem(String testName) {
766         // Perform setup.
767         setupDeleteNonExistent();
768
769         // Submit the request to the service and store the response.
770         AuthorityClient client = (AuthorityClient) getClientInstance();
771         Response res = client.deleteItem(knownResourceId, NON_EXISTENT_ID);
772         int statusCode;
773         try {
774                 statusCode = res.getStatus();
775         } finally {
776                 res.close();
777         }
778
779         // Check the status code of the response: does it match
780         // the expected response(s)?
781         if (logger.isDebugEnabled()) {
782             logger.debug(testName + ": status = " + statusCode);
783         }
784         Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
785                 invalidStatusCodeMessage(testRequestType, statusCode));
786         Assert.assertEquals(statusCode, testExpectedStatusCode);
787     }
788     
789     protected String getServicePathItemsComponent() {
790         return AuthorityClient.ITEMS;
791     }
792     
793         public PoxPayloadOut createItemRequestTypeInstance(AUTHORITY_ITEM_TYPE itemTypeInstance) {
794                 PoxPayloadOut result = null;
795                 
796         AuthorityClient client = (AuthorityClient) getClientInstance();
797         PoxPayloadOut payloadOut = new PoxPayloadOut(this.getServicePathItemsComponent());
798         PayloadOutputPart part = payloadOut.addPart(client.getItemCommonPartName(), itemTypeInstance);
799         result = payloadOut;
800                 
801                 return result;
802         }
803
804         /**
805          * Update an Authority item.
806          * 
807          * @param testName
808          * @throws Exception
809          */
810     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
811                 dependsOnMethods = {"readItem", "CRUDTests", "verifyIgnoredUpdateWithInAuthority"})
812     public void updateItem(String testName) throws Exception {
813         // Perform setup.
814         setupUpdate();
815         AUTHORITY_ITEM_TYPE theUpdate = null;
816
817         // Retrieve the contents of a resource to update.
818         AuthorityClient client = (AuthorityClient)this.getClientInstance();
819         Response res = client.readItem(knownResourceId, knownItemResourceId);
820         try {
821                 if (logger.isDebugEnabled()) {
822                     logger.debug(testName + ": read status = " + res.getStatus());
823                 }
824                 Assert.assertEquals(res.getStatus(), testExpectedStatusCode);
825         
826                 if (logger.isDebugEnabled()) {
827                     logger.debug("got Authority item to update with ID: "
828                             + knownItemResourceId
829                             + " in authority: " + knownResourceId);
830                 }
831                 AUTHORITY_ITEM_TYPE authorityItem = extractItemCommonPartValue(res);
832                 Assert.assertNotNull(authorityItem);
833
834                 // Update the contents of this resource.
835                 theUpdate = updateItemInstance(authorityItem);
836                 if (logger.isDebugEnabled()) {
837                     logger.debug("\n\nTo be updated fields: CSID = "  + knownItemResourceId + "\n"
838                                 + objectAsXmlString(theUpdate));
839                 }
840         } finally {
841                 res.close();
842         }
843
844         // Submit the updated resource to the service and store the response.
845         PoxPayloadOut output = this.createItemRequestTypeInstance(theUpdate);
846         res = client.updateItem(knownResourceId, knownItemResourceId, output);
847         try {
848                 int statusCode = res.getStatus();
849         
850                 // Check the status code of the response: does it match the expected response(s)?
851                 if (logger.isDebugEnabled()) {
852                     logger.debug("updateItem: status = " + statusCode);
853                 }
854                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
855                         invalidStatusCodeMessage(testRequestType, statusCode));
856                 Assert.assertEquals(statusCode, testExpectedStatusCode);
857         
858                 // Retrieve the updated resource and verify that its contents exist.
859                 AUTHORITY_ITEM_TYPE updatedVocabularyItem = extractItemCommonPartValue(res);
860                 Assert.assertNotNull(updatedVocabularyItem);
861
862                 compareUpdatedItemInstances(theUpdate, updatedVocabularyItem);
863         } finally {
864                 res.close();
865         }
866     }
867     
868     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
869                 dependsOnMethods = {"readItem", "CRUDTests", "veryifySyncWithSAS"})
870     public void updateLocalItemWithSync(String testName) throws Exception {
871         // Perform setup.
872         setupUpdate();
873         AUTHORITY_ITEM_TYPE theUpdate = null;
874
875         // Retrieve the contents of a shared authority item that we're going to update.
876         AUTHORITY_ITEM_TYPE sasAuthorityItem = null;
877         AuthorityClient sasClient = (AuthorityClient) this.getSASClientInstance();
878         Response res = sasClient.readNamedItemInNamedAuthority(knownSASAuthorityResourceIdentifier, knownSASItemIdentifiersList.get(0));
879         try {
880                 if (logger.isDebugEnabled()) {
881                     logger.debug(testName + ": read status = " + res.getStatus());
882                 }
883                 Assert.assertEquals(res.getStatus(), testExpectedStatusCode);
884         
885                 sasAuthorityItem = extractItemCommonPartValue(res);  // This is a SAS authority item
886                 Assert.assertNotNull(sasAuthorityItem);
887         } finally {
888                 res.close();
889         }
890
891         // Update the contents of this authority item so we can post an UPDATE to the server
892         theUpdate = updateItemInstance(sasAuthorityItem);
893
894         // Submit the updated authority item and check the response.
895         PoxPayloadOut output = this.createItemRequestTypeInstance(theUpdate);
896         res = sasClient.updateNamedItemInNamedAuthority(knownSASAuthorityResourceIdentifier, knownSASItemIdentifiersList.get(0), output);
897         AUTHORITY_ITEM_TYPE updatedSASAuthorityItem = null;
898         try {
899                 int statusCode = res.getStatus();
900         
901                 // Check the status code of the response: does it match the expected response(s)?
902                 if (logger.isDebugEnabled()) {
903                     logger.debug("updateItem: status = " + statusCode);
904                 }
905                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
906                         invalidStatusCodeMessage(testRequestType, statusCode));
907                 Assert.assertEquals(statusCode, testExpectedStatusCode);
908         
909                 // Retrieve the updated authority item and verify that its contents exist.
910                 updatedSASAuthorityItem = extractItemCommonPartValue(res);
911                 Assert.assertNotNull(updatedSASAuthorityItem);
912
913                 compareUpdatedItemInstances(theUpdate, updatedSASAuthorityItem);
914         } finally {
915                 res.close();
916         }
917         
918         // Synchronize the local item's parent authority and verify the update we just made
919         // to the SAS item appears locally after the sync
920         setupSync();
921         AuthorityClient localClient = (AuthorityClient) this.getClientInstance();
922         Response response = localClient.syncByName(knownSASAuthorityResourceIdentifier); // Notice we're using the Short ID (short ID is the same on the local and SAS)
923         try {
924                 int statusCode = response.getStatus();
925                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode), invalidStatusCodeMessage(testRequestType, statusCode));
926                 Assert.assertEquals(statusCode, testExpectedStatusCode);
927         } finally {
928                 response.close();
929         }        
930         
931         setupRead();
932         res = localClient.readNamedItemInNamedAuthority(knownSASAuthorityResourceIdentifier, knownSASItemIdentifiersList.get(0));
933         try {
934                 Assert.assertEquals(res.getStatus(), testExpectedStatusCode);
935                 AUTHORITY_ITEM_TYPE syncedAuthorityItem = extractItemCommonPartValue(res);
936                 Assert.assertNotNull(syncedAuthorityItem);
937                 compareUpdatedItemInstances(syncedAuthorityItem, updatedSASAuthorityItem);
938         } finally {
939                 res.close();
940         }
941     }    
942     
943     protected abstract PoxPayloadOut createNonExistenceItemInstance(String commonPartName, String identifier);
944     
945     /* (non-Javadoc)
946      * @see org.collectionspace.services.client.test.ServiceTest#updateNonExistent(java.lang.String)
947      */
948     @Test(dataProvider = "testName",
949         dependsOnMethods = {"create", "update", "updateNonExistent"})
950     public void updateNonExistentItem(String testName) throws Exception {
951         // Perform setup.
952         setupUpdateNonExistent();
953
954         // Submit the request to the service and store the response.
955         // Note: The ID used in this 'create' call may be arbitrary.
956         // The only relevant ID may be the one used in update(), below.
957         AuthorityClient client = (AuthorityClient)this.getClientInstance();
958         PoxPayloadOut multipart = createNonExistenceItemInstance(client.getItemCommonPartName(), NON_EXISTENT_ID);
959         Response res = client.updateItem(knownResourceId, NON_EXISTENT_ID, multipart);
960         try {
961                 int statusCode = res.getStatus();
962         
963                 // Check the status code of the response: does it match
964                 // the expected response(s)?
965                 if (logger.isDebugEnabled()) {
966                         logger.debug(testName + ": status = " + statusCode);
967                 }
968                 Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
969                                 invalidStatusCodeMessage(testRequestType, statusCode));
970                 Assert.assertEquals(statusCode, testExpectedStatusCode);
971         } finally {
972                 res.close();
973         }
974     }
975         
976     //
977     // Methods to persuade TestNG to follow the correct test dependency path
978     //
979     
980     @Test(dataProvider = "testName",
981                 dependsOnMethods = {"createItem"})
982     public void baseAuthorityTests(String testName) {
983         // Do nothing.  Here just to setup a test dependency chain.
984     }
985     
986     /*
987      * For convenience and terseness, this test method is the base of the test execution dependency chain.  Other test methods may
988      * refer to this method in their @Test annotation declarations.
989      */
990     @Override
991     @Test(dataProvider = "testName",
992                 dependsOnMethods = {
993                         "org.collectionspace.services.client.test.AbstractServiceTestImpl.baseCRUDTests"})    
994         public void CRUDTests(String testName) {
995                 // TODO Auto-generated method stub
996         }
997         
998     @Override
999     public void cleanUp() {
1000         String noTest = System.getProperty("noTestCleanup");
1001         if (Boolean.TRUE.toString().equalsIgnoreCase(noTest)) {
1002             if (logger.isDebugEnabled()) {
1003                 logger.debug("Skipping Cleanup phase ...");
1004             }
1005             return;
1006         }
1007         
1008         AuthorityClient client = (AuthorityClient) this.getClientInstance();
1009         String parentResourceId;
1010         String itemResourceId;
1011         //
1012         // Clean up all authority item resources.
1013         //
1014         for (Map.Entry<String, String> entry : allResourceItemIdsCreated.entrySet()) {
1015             itemResourceId = entry.getKey();
1016             parentResourceId = entry.getValue();
1017             Response response = client.deleteItem(parentResourceId, itemResourceId);
1018             try {
1019                 int status = response.getStatus();
1020                 if (status != Response.Status.OK.getStatusCode()) {
1021                         logger.debug(String.format("Could not deleted authority item '%s' in authority '%s'.",
1022                                         itemResourceId, parentResourceId));
1023                 }
1024             } finally {
1025                 response.close();
1026             }
1027         }
1028         //
1029         // Clean up authority items that were the result of a sync with the SAS
1030         // all the IDs are URN (not CSIDs).  The URNs work for the local items as well
1031         // as the SAS items.
1032         //
1033         for (Map.Entry<String, String> entry : allSASResourceItemIdsCreated.entrySet()) {
1034             itemResourceId = entry.getKey();
1035             parentResourceId = entry.getValue();
1036             // Note: Any non-success responses from the delete operation
1037             // below are ignored and not reported.
1038             client.deleteItem(parentResourceId, itemResourceId).close();
1039         }
1040         //
1041         // Clean up authority items on the SAS using the SAS client.
1042         //
1043         client = (AuthorityClient) this.getSASClientInstance();
1044         for (Map.Entry<String, String> entry : allSASResourceItemIdsCreated.entrySet()) {
1045             itemResourceId = entry.getKey();
1046             parentResourceId = entry.getValue();
1047             client.deleteItem(parentResourceId, itemResourceId).close();
1048         }
1049         //
1050         // Finally, call out superclass's cleanUp method to deleted the local authorities
1051         //
1052         super.cleanUp();
1053         //
1054         // Call out superclass's cleanUp method to delete the SAS authorities
1055         //
1056         super.cleanUp(client);        
1057     }
1058     
1059         protected String getTestAuthorityItemShortId() {
1060                 return getTestAuthorityItemShortId(false);
1061         }
1062
1063         protected String getTestAuthorityItemShortId(boolean makeUnique) {
1064                 String result = TEST_SHORTID;
1065                 
1066                 if (makeUnique == true) {
1067                         result = result + System.currentTimeMillis() + Math.abs(random.nextInt());
1068                 }
1069                 
1070                 return result;
1071         }
1072 }