]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
f993942dbcc62e480b64b165e57bf5eb9d3d3bdf
[tmp/jakarta-migration.git] /
1 /**
2  * This document is a part of the source code and related artifacts
3  * for CollectionSpace, an open source collections management system
4  * for museums and related institutions:
5  *
6  * http://www.collectionspace.org
7  * http://wiki.collectionspace.org
8  *
9  * Copyright © 2009 Regents of the University of California
10  *
11  * Licensed under the Educational Community License (ECL), Version 2.0.
12  * You may not use this file except in compliance with this License.
13  *
14  * You may obtain a copy of the ECL 2.0 License at
15  * https://source.collectionspace.org/collection-space/LICENSE.txt
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  */
23 package org.collectionspace.services.client.test;
24
25 import java.util.ArrayList;
26 import java.util.List;
27 import javax.ws.rs.core.MediaType;
28 import javax.ws.rs.core.Response;
29
30 //import org.collectionspace.services.client.AbstractServiceClientImpl;
31 import org.collectionspace.services.client.CollectionObjectClient;
32 import org.collectionspace.services.client.CollectionSpaceClient;
33 import org.collectionspace.services.collectionobject.CollectionobjectsCommon;
34 import org.collectionspace.services.collectionobject.domain.naturalhistory.CollectionobjectsNaturalhistory;
35 import org.collectionspace.services.collectionobject.CollectionobjectsCommonList;
36 import org.collectionspace.services.collectionobject.ResponsibleDepartmentList;
37 import org.collectionspace.services.jaxb.AbstractCommonList;
38
39 import org.jboss.resteasy.client.ClientResponse;
40 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
41 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
42 import org.jboss.resteasy.plugins.providers.multipart.OutputPart;
43 import org.testng.Assert;
44 import org.testng.annotations.AfterClass;
45 import org.testng.annotations.Test;
46
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49
50 /**
51  * CollectionObjectServiceTest, carries out tests against a
52  * deployed and running CollectionObject Service.
53  *
54  * $LastChangedRevision$
55  * $LastChangedDate$
56  */
57 public class CollectionObjectServiceTest extends AbstractServiceTestImpl {
58
59     /** The logger. */
60     private final Logger logger =
61             LoggerFactory.getLogger(CollectionObjectServiceTest.class);
62     // Instance variables specific to this test.
63     /** The known resource id. */
64     private String knownResourceId = null;
65     
66     /** The all resource ids created. */
67     private List<String> allResourceIdsCreated = new ArrayList<String>();
68     
69     /** The multivalue. */
70     private boolean multivalue; //toggle
71
72     /**
73      * Gets the logger.
74      *
75      * @return the logger
76      */
77     private Logger getLogger() {
78         return this.logger;
79     }
80
81     /* (non-Javadoc)
82      * @see org.collectionspace.services.client.test.BaseServiceTest#getServicePathComponent()
83      */
84     @Override
85     protected String getServicePathComponent() {
86         return new CollectionObjectClient().getServicePathComponent();
87     }
88     
89     /* (non-Javadoc)
90      * @see org.collectionspace.services.client.test.BaseServiceTest#getClientInstance()
91      */
92     @Override
93     protected CollectionSpaceClient getClientInstance() {
94         return new CollectionObjectClient();
95     }
96     
97     /* (non-Javadoc)
98      * @see org.collectionspace.services.client.test.BaseServiceTest#getAbstractCommonList(org.jboss.resteasy.client.ClientResponse)
99      */
100     @Override
101         protected AbstractCommonList getAbstractCommonList(
102                         ClientResponse<AbstractCommonList> response) {
103         return response.getEntity(CollectionobjectsCommonList.class);
104     }
105  
106     // ---------------------------------------------------------------
107     // CRUD tests : CREATE tests
108     // ---------------------------------------------------------------
109     // Success outcomes
110     /* (non-Javadoc)
111      * @see org.collectionspace.services.client.test.ServiceTest#create(java.lang.String)
112      */
113     @Override
114     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
115     public void create(String testName) throws Exception {
116
117         // Perform setup, such as initializing the type of service request
118         // (e.g. CREATE, DELETE), its valid and expected status codes, and
119         // its associated HTTP method name (e.g. POST, DELETE).
120         setupCreate(testName);
121
122         // Submit the request to the service and store the response.
123         CollectionObjectClient client = new CollectionObjectClient();
124         String identifier = createIdentifier();
125         MultipartOutput multipart =
126                 createCollectionObjectInstance(client.getCommonPartName(), identifier);
127         ClientResponse<Response> res = client.create(multipart);
128         int statusCode = res.getStatus();
129
130         // Check the status code of the response: does it match
131         // the expected response(s)?
132         //
133         // Specifically:
134         // Does it fall within the set of valid status codes?
135         // Does it exactly match the expected status code?
136         if (logger.isDebugEnabled()) {
137             logger.debug(testName + ": status = " + statusCode);
138         }
139         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
140                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
141         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
142
143         // Store the ID returned from the first resource created
144         // for additional tests below.
145         if (knownResourceId == null) {
146             knownResourceId = extractId(res);
147             if (logger.isDebugEnabled()) {
148                 logger.debug(testName + ": knownResourceId=" + knownResourceId);
149             }
150         }
151
152         // Store the IDs from every resource created by tests,
153         // so they can be deleted after tests have been run.
154         allResourceIdsCreated.add(extractId(res));
155     }
156
157
158     /*
159      * Tests to diagnose and verify the fixed status of CSPACE-1026,
160      * "Whitespace at certain points in payload cause failure"
161      */
162     /**
163      * Creates the from xml cambridge.
164      *
165      * @param testName the test name
166      * @throws Exception the exception
167      */
168     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
169         dependsOnMethods = {"create", "testSubmitRequest"})
170     public void createFromXmlCambridge(String testName) throws Exception {
171         String newId =
172             createFromXmlFile(testName, "./test-data/testCambridge.xml", true);
173         testSubmitRequest(newId);
174     }
175
176     /**
177      * Creates the from xml rfw s1.
178      *
179      * @param testName the test name
180      * @throws Exception the exception
181      */
182     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
183         dependsOnMethods = {"create", "testSubmitRequest"})
184     public void createFromXmlRFWS1(String testName) throws Exception {
185         String testDataDir = System.getProperty("test-data.fileName");
186         String newId =
187             //createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp1.xml", false);
188                 createFromXmlFile(testName, testDataDir + "/repfield_whitesp1.xml", false);
189         testSubmitRequest(newId);
190     }
191
192     /**
193      * Creates the from xml rfw s2.
194      *
195      * @param testName the test name
196      * @throws Exception the exception
197      */
198     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
199         dependsOnMethods = {"create", "testSubmitRequest"})
200     public void createFromXmlRFWS2(String testName) throws Exception {
201         String testDataDir = System.getProperty("test-data.fileName");
202         String newId =
203             //createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp2.xml", false);
204                 createFromXmlFile(testName, testDataDir + "/repfield_whitesp2.xml", false);
205         testSubmitRequest(newId);
206     }
207
208     /**
209      * Creates the from xml rfw s3.
210      *
211      * @param testName the test name
212      * @throws Exception the exception
213      */
214     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
215         dependsOnMethods = {"create", "testSubmitRequest"})
216     public void createFromXmlRFWS3(String testName) throws Exception {
217         String testDataDir = System.getProperty("test-data.fileName");
218         String newId =
219             //createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp3.xml", false);
220                 createFromXmlFile(testName, testDataDir + "/repfield_whitesp3.xml", false);
221         testSubmitRequest(newId);
222     }
223
224     /**
225      * Creates the from xml rfw s4.
226      *
227      * @param testName the test name
228      * @throws Exception the exception
229      */
230     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
231         dependsOnMethods = {"create", "testSubmitRequest"})
232     public void createFromXmlRFWS4(String testName) throws Exception {
233         String testDataDir = System.getProperty("test-data.fileName");
234         String newId =
235             createFromXmlFile(testName, testDataDir + "/repfield_whitesp4.xml", false);
236         testSubmitRequest(newId);
237     }
238
239     /*
240      * Tests to diagnose and verify the fixed status of CSPACE-1248,
241      * "Wedged records created!" (i.e. records with child repeatable
242      * fields, which contain null values, can be successfully created
243      * but an error occurs on trying to retrieve those records).
244      */
245     /**
246      * Creates the with null value repeatable field.
247      *
248      * @param testName the test name
249      * @throws Exception the exception
250      */
251     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
252         dependsOnMethods = {"create", "testSubmitRequest"})
253     public void createWithNullValueRepeatableField(String testName) throws Exception {
254         String testDataDir = System.getProperty("test-data.fileName");
255         String newId =
256             createFromXmlFile(testName, testDataDir + "/repfield_null1.xml", false);
257         if (logger.isDebugEnabled()) {
258             logger.debug("Successfully created record with null value repeatable field.");
259             logger.debug("Attempting to retrieve just-created record ...");
260         }
261         testSubmitRequest(newId);
262     }
263     
264     /* (non-Javadoc)
265      * @see org.collectionspace.services.client.test.ServiceTest#createList()
266      */
267     @Override
268     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
269     dependsOnMethods = {"create"})
270     public void createList(String testName) throws Exception {
271         this.createPaginatedList(testName, DEFAULT_LIST_SIZE);
272     }
273
274     // Failure outcomes
275     // Placeholders until the three tests below can be uncommented.
276     // See Issue CSPACE-401.
277     /* (non-Javadoc)
278      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#createWithEmptyEntityBody(java.lang.String)
279      */
280     @Override
281     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
282     public void createWithEmptyEntityBody(String testName) throws Exception {
283         //FIXME: Should this test really be empty?
284     }
285
286    /**
287     * Test how the service handles XML that is not well formed,
288     * when sent in the payload of a Create request.
289     *
290     * @param testName  The name of this test method.  This name is supplied
291     *     automatically, via reflection, by a TestNG 'data provider' in
292     *     a base class.
293     */
294     @Override
295     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
296     public void createWithMalformedXml(String testName) throws Exception {
297         setupCreate(testName);
298     }
299
300     /* (non-Javadoc)
301      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#createWithWrongXmlSchema(java.lang.String)
302      */
303     @Override
304     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
305     public void createWithWrongXmlSchema(String testName) throws Exception {
306         //FIXME: Should this test really be empty?
307     }
308
309
310 /*
311     @Override
312     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
313     dependsOnMethods = {"create", "testSubmitRequest"})
314     public void createWithEmptyEntityBody(String testName) throwsException {
315
316     // Perform setup.
317     setupCreateWithEmptyEntityBody(testName);
318
319     // Submit the request to the service and store the response.
320     String method = REQUEST_TYPE.httpMethodName();
321     String url = getServiceRootURL();
322     String mediaType = MediaType.APPLICATION_XML;
323     final String entity = "";
324     int statusCode = submitRequest(method, url, mediaType, entity);
325
326     // Check the status code of the response: does it match
327     // the expected response(s)?
328     if(logger.isDebugEnabled()){
329     logger.debug(testName + ": url=" + url +
330     " status=" + statusCode);
331     }
332     Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
333     invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
334     Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
335     }
336
337     @Override
338     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
339     dependsOnMethods = {"create", "testSubmitRequest"})
340     public void createWithMalformedXml(String testName) throws Exception {
341
342     // Perform setup.
343     setupCreateWithMalformedXml(testName);
344
345     // Submit the request to the service and store the response.
346     String method = REQUEST_TYPE.httpMethodName();
347     String url = getServiceRootURL();
348     String mediaType = MediaType.APPLICATION_XML;
349     final String entity = MALFORMED_XML_DATA; // Constant from base class.
350     int statusCode = submitRequest(method, url, mediaType, entity);
351
352     // Check the status code of the response: does it match
353     // the expected response(s)?
354     if(logger.isDebugEnabled()){
355     logger.debug(testName + ": url=" + url +
356     " status=" + statusCode);
357     }
358     Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
359     invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
360     Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
361     }
362
363     @Override
364     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
365     dependsOnMethods = {"create", "testSubmitRequest"})
366     public void createWithWrongXmlSchema(String testName) throws Exception {
367
368     // Perform setup.
369     setupCreateWithWrongXmlSchema(testName);
370
371     // Submit the request to the service and store the response.
372     String method = REQUEST_TYPE.httpMethodName();
373     String url = getServiceRootURL();
374     String mediaType = MediaType.APPLICATION_XML;
375     final String entity = WRONG_XML_SCHEMA_DATA;
376     int statusCode = submitRequest(method, url, mediaType, entity);
377
378     // Check the status code of the response: does it match
379     // the expected response(s)?
380     if(logger.isDebugEnabled()){
381     logger.debug(testName + ": url=" + url +
382     " status=" + statusCode);
383     }
384     Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
385     invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
386     Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
387     }
388 */
389
390    /**
391     * Test how the service handles, in a Create request, payloads
392     * containing null values (or, in the case of String fields,
393     * empty String values) in one or more fields which must be
394     * present and are required to contain non-empty values.
395     *
396     * This is a test of code and/or configuration in the service's
397     * validation routine(s).
398     *
399     * @param testName  The name of this test method.  This name is supplied
400     *     automatically, via reflection, by a TestNG 'data provider' in
401     *     a base class.
402     * @throws Exception 
403     */
404     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
405     public void createWithRequiredValuesNullOrEmpty(String testName) throws Exception {
406         setupCreate(testName);
407
408         // Build a payload with invalid content, by omitting a
409         // field (objectNumber) which must be present, and in which
410         // a non-empty value is required, as enforced by the service's
411         // validation routine(s).
412         CollectionobjectsCommon collectionObject = new CollectionobjectsCommon();
413         collectionObject.setTitle("atitle");
414         collectionObject.setObjectName("some name");
415
416         // Submit the request to the service and store the response.
417         CollectionObjectClient client = new CollectionObjectClient();
418         MultipartOutput multipart =
419                 createCollectionObjectInstance(client.getCommonPartName(), collectionObject, null);
420         ClientResponse<Response> res = client.create(multipart);
421         int statusCode = res.getStatus();
422
423         // Read the response and verify that the create attempt failed.
424         if (logger.isDebugEnabled()) {
425             logger.debug(testName + ": status = " + statusCode);
426         }
427         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
428                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
429         Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
430
431         // FIXME: Consider splitting off the following into its own test method.
432         
433         // Build a payload with invalid content, by setting a value to the
434         // empty String, in a field that requires a non-empty value,
435         // as enforced by the service's validation routine(s).
436         collectionObject = new CollectionobjectsCommon();
437         collectionObject.setTitle("atitle");
438         collectionObject.setObjectName("some name");
439         collectionObject.setObjectNumber("");
440
441         // Submit the request to the service and store the response.
442         multipart =
443             createCollectionObjectInstance(client.getCommonPartName(), collectionObject, null);
444         res = client.create(multipart);
445         statusCode = res.getStatus();
446
447         // Read the response and verify that the create attempt failed.
448         if (logger.isDebugEnabled()) {
449             logger.debug(testName + ": status = " + statusCode);
450         }
451         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
452                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
453         Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
454
455     }
456
457
458     // ---------------------------------------------------------------
459     // CRUD tests : READ tests
460     // ---------------------------------------------------------------
461     // Success outcomes
462     /* (non-Javadoc)
463      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#read(java.lang.String)
464      */
465     @Override
466     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
467     dependsOnMethods = {"create"})
468     public void read(String testName) throws Exception {
469
470         // Perform setup.
471         setupRead(testName);
472
473         // Submit the request to the service and store the response.
474         CollectionObjectClient client = new CollectionObjectClient();
475         ClientResponse<MultipartInput> res = client.read(knownResourceId);
476         int statusCode = res.getStatus();
477
478         // Check the status code of the response: does it match
479         // the expected response(s)?
480         if (logger.isDebugEnabled()) {
481             logger.debug(testName + ": status = " + statusCode);
482         }
483         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
484                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
485         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
486
487         MultipartInput input = (MultipartInput) res.getEntity();
488
489         if (logger.isDebugEnabled()) {
490             logger.debug(testName + ": Reading Common part ...");
491         }
492         CollectionobjectsCommon collectionObject =
493                 (CollectionobjectsCommon) extractPart(input,
494                 client.getCommonPartName(), CollectionobjectsCommon.class);
495         Assert.assertNotNull(collectionObject);
496
497         if (logger.isDebugEnabled()) {
498             logger.debug(testName + ": Reading Natural History part ...");
499         }
500         CollectionobjectsNaturalhistory conh =
501                 (CollectionobjectsNaturalhistory) extractPart(input,
502                 getNHPartName(), CollectionobjectsNaturalhistory.class);
503         Assert.assertNotNull(conh);
504     }
505
506     // Failure outcomes
507     /* (non-Javadoc)
508      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#readNonExistent(java.lang.String)
509      */
510     @Override
511     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
512     dependsOnMethods = {"read"})
513     public void readNonExistent(String testName) throws Exception {
514
515         // Perform setup.
516         setupReadNonExistent(testName);
517
518         // Submit the request to the service and store the response.
519         CollectionObjectClient client = new CollectionObjectClient();
520         ClientResponse<MultipartInput> res = client.read(NON_EXISTENT_ID);
521         int statusCode = res.getStatus();
522
523         // Check the status code of the response: does it match
524         // the expected response(s)?
525         if (logger.isDebugEnabled()) {
526             logger.debug(testName + ": status = " + statusCode);
527         }
528         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
529                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
530         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
531     }
532
533     
534     // ---------------------------------------------------------------
535     // CRUD tests : READ_LIST tests
536     // ---------------------------------------------------------------
537     // Success outcomes
538     /* (non-Javadoc)
539      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#readList(java.lang.String)
540      */
541     @Override
542     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
543     dependsOnMethods = {"createList", "read"})
544     public void readList(String testName) throws Exception {
545
546         // Perform setup.
547         setupReadList(testName);
548
549         // Submit the request to the service and store the response.
550         CollectionObjectClient client = new CollectionObjectClient();
551         ClientResponse<CollectionobjectsCommonList> res = client.readList();
552         CollectionobjectsCommonList list = res.getEntity();
553         int statusCode = res.getStatus();
554
555         // Check the status code of the response: does it match
556         // the expected response(s)?
557         if (logger.isDebugEnabled()) {
558             logger.debug(testName + ": status = " + statusCode);
559         }
560         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
561                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
562         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
563
564         // Optionally output additional data about list members for debugging.
565         boolean iterateThroughList = false;
566         if (iterateThroughList && logger.isDebugEnabled()) {
567             List<CollectionobjectsCommonList.CollectionObjectListItem> items =
568                     list.getCollectionObjectListItem();
569             int i = 0;
570
571             for (CollectionobjectsCommonList.CollectionObjectListItem item : items) {
572                 logger.debug(testName + ": list-item[" + i + "] csid="
573                         + item.getCsid());
574                 logger.debug(testName + ": list-item[" + i + "] objectNumber="
575                         + item.getObjectNumber());
576                 logger.debug(testName + ": list-item[" + i + "] URI="
577                         + item.getUri());
578                 i++;
579
580             }
581         }
582     }
583
584     // Failure outcomes
585     // None at present.
586     // ---------------------------------------------------------------
587     // CRUD tests : UPDATE tests
588     // ---------------------------------------------------------------
589     // Success outcomes
590     /* (non-Javadoc)
591      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#update(java.lang.String)
592      */
593     @Override
594     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
595     dependsOnMethods = {"read"})
596     public void update(String testName) throws Exception {
597
598         // Perform setup.
599         setupUpdate(testName);
600
601         // Read an existing resource that will be updated.
602         ClientResponse<MultipartInput> res = updateRetrieve(testName, knownResourceId);
603
604         // Extract its common part.
605         CollectionObjectClient client = new CollectionObjectClient();
606         MultipartInput input = (MultipartInput) res.getEntity();
607         CollectionobjectsCommon collectionObject =
608                 (CollectionobjectsCommon) extractPart(input,
609                 client.getCommonPartName(), CollectionobjectsCommon.class);
610         Assert.assertNotNull(collectionObject);
611
612         // Change the content of one or more fields in the common part.
613         collectionObject.setObjectNumber("updated-" + collectionObject.getObjectNumber());
614         collectionObject.setObjectName("updated-" + collectionObject.getObjectName());
615         if (logger.isDebugEnabled()) {
616             logger.debug("sparse update that will be sent in update request:");
617             logger.debug(objectAsXmlString(collectionObject,
618                     CollectionobjectsCommon.class));
619         }
620
621         // Send the changed resource to be updated.
622         res = updateSend(testName, knownResourceId, collectionObject);
623         int statusCode = res.getStatus();
624         // Check the status code of the response: does it match the expected response(s)?
625         if (logger.isDebugEnabled()) {
626             logger.debug(testName + ": status = " + statusCode);
627         }
628         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
629                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
630         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
631
632         // Read the response and verify that the resource was correctly updated.
633         input = (MultipartInput) res.getEntity();
634         CollectionobjectsCommon updatedCollectionObject =
635                 (CollectionobjectsCommon) extractPart(input,
636                 client.getCommonPartName(), CollectionobjectsCommon.class);
637         Assert.assertNotNull(updatedCollectionObject);
638         Assert.assertEquals(updatedCollectionObject.getObjectName(),
639                 collectionObject.getObjectName(),
640                 "Data in updated object did not match submitted data.");
641
642     }
643
644     /**
645      * Update retrieve.
646      *
647      * @param testName the test name
648      * @param id the id
649      * @return the client response
650      */
651     private ClientResponse<MultipartInput> updateRetrieve(String testName, String id) {
652         final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
653         CollectionObjectClient client = new CollectionObjectClient();
654         ClientResponse<MultipartInput> res = client.read(id);
655         if (logger.isDebugEnabled()) {
656             logger.debug("read in updateRetrieve for " + testName + " status = " + res.getStatus());
657         }
658         Assert.assertEquals(res.getStatus(), EXPECTED_STATUS);
659         if (logger.isDebugEnabled()) {
660             logger.debug("got object to updateRetrieve for " + testName + " with ID: " + id);
661         }
662         return res;
663     }
664
665     /**
666      * Update send.
667      *
668      * @param testName the test name
669      * @param id the id
670      * @param collectionObject the collection object
671      * @return the client response
672      */
673     private ClientResponse<MultipartInput> updateSend(String testName, String id,
674             CollectionobjectsCommon collectionObject) {
675         MultipartOutput output = new MultipartOutput();
676         OutputPart commonPart = output.addPart(collectionObject, MediaType.APPLICATION_XML_TYPE);
677         CollectionObjectClient client = new CollectionObjectClient();
678         commonPart.getHeaders().add("label", client.getCommonPartName());
679         ClientResponse<MultipartInput> res = client.update(knownResourceId, output);
680         return res;
681     }
682
683     // Failure outcomes
684     // Placeholders until the three tests below can be uncommented.
685     // See Issue CSPACE-401.
686     /* (non-Javadoc)
687      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateWithEmptyEntityBody(java.lang.String)
688      */
689     @Override
690     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
691     dependsOnMethods = {"read"})
692     public void updateWithEmptyEntityBody(String testName) throws Exception {
693         //FIXME: Should this test really be empty?
694     }
695
696    /**
697     * Test how the service handles XML that is not well formed,
698     * when sent in the payload of an Update request.
699     *
700     * @param testName  The name of this test method.  This name is supplied
701     *     automatically, via reflection, by a TestNG 'data provider' in
702     *     a base class.
703     */
704     @Override
705     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
706     dependsOnMethods = {"read"})
707     public void updateWithMalformedXml(String testName) throws Exception {
708         //FIXME: Should this test really be empty?
709     }
710
711     /* (non-Javadoc)
712      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateWithWrongXmlSchema(java.lang.String)
713      */
714     @Override
715     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
716     dependsOnMethods = {"read"})
717     public void updateWithWrongXmlSchema(String testName) throws Exception {
718         //FIXME: Should this test really be empty?
719     }
720
721 /*
722     @Override
723     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
724     dependsOnMethods = {"create", "update", "testSubmitRequest"})
725     public void updateWithEmptyEntityBody(String testName) throws Exception {
726
727     // Perform setup.
728     setupUpdateWithEmptyEntityBody(testName);
729
730     // Submit the request to the service and store the response.
731     String method = REQUEST_TYPE.httpMethodName();
732     String url = getResourceURL(knownResourceId);
733     String mediaType = MediaType.APPLICATION_XML;
734     final String entity = "";
735     int statusCode = submitRequest(method, url, mediaType, entity);
736
737     // Check the status code of the response: does it match
738     // the expected response(s)?
739     if(logger.isDebugEnabled()){
740     logger.debug(testName + ": url=" + url +
741     " status=" + statusCode);
742     }
743     Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
744     invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
745     Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
746     }
747
748     @Override
749     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
750     dependsOnMethods = {"create", "update", "testSubmitRequest"})
751     public void updateWithMalformedXml() throws Exception {
752
753     // Perform setup.
754     setupUpdateWithMalformedXml(testName);
755
756     // Submit the request to the service and store the response.
757     String method = REQUEST_TYPE.httpMethodName();
758     String url = getResourceURL(knownResourceId);
759     final String entity = MALFORMED_XML_DATA;
760     String mediaType = MediaType.APPLICATION_XML;
761     int statusCode = submitRequest(method, url, mediaType, entity);
762
763     // Check the status code of the response: does it match
764     // the expected response(s)?
765     if(logger.isDebugEnabled()){
766     logger.debug(testName + ": url=" + url +
767     " status=" + statusCode);
768     }
769     Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
770     invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
771     Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
772     }
773
774     @Override
775     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
776     dependsOnMethods = {"create", "update", "testSubmitRequest"})
777     public void updateWithWrongXmlSchema(String testName) throws Exception {
778
779     // Perform setup.
780     setupUpdateWithWrongXmlSchema(String testName);
781
782     // Submit the request to the service and store the response.
783     String method = REQUEST_TYPE.httpMethodName();
784     String url = getResourceURL(knownResourceId);
785     String mediaType = MediaType.APPLICATION_XML;
786     final String entity = WRONG_XML_SCHEMA_DATA;
787     int statusCode = submitRequest(method, url, mediaType, entity);
788
789     // Check the status code of the response: does it match
790     // the expected response(s)?
791     if(logger.isDebugEnabled()){
792     logger.debug(testName + ": url=" + url +
793     " status=" + statusCode);
794     }
795     Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
796     invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
797     Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
798     }
799 */
800
801     /* (non-Javadoc)
802  * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateNonExistent(java.lang.String)
803  */
804 @Override
805     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
806     dependsOnMethods = {"update", "testSubmitRequest"})
807     public void updateNonExistent(String testName) throws Exception {
808
809         // Perform setup.
810         setupUpdateNonExistent(testName);
811
812         // Submit the request to the service and store the response.
813         //
814         // Note: The ID used in this 'create' call may be arbitrary.
815         // The only relevant ID may be the one used in updateCollectionObject(), below.
816         CollectionObjectClient client = new CollectionObjectClient();
817         MultipartOutput multipart =
818                 createCollectionObjectInstance(client.getCommonPartName(),
819                 NON_EXISTENT_ID);
820         ClientResponse<MultipartInput> res =
821                 client.update(NON_EXISTENT_ID, multipart);
822         int statusCode = res.getStatus();
823
824         // Check the status code of the response: does it match
825         // the expected response(s)?
826         if (logger.isDebugEnabled()) {
827             logger.debug(testName + ": status = " + statusCode);
828         }
829         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
830                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
831         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
832     }
833
834    /**
835     * Test how the service handles, in an Update request, payloads
836     * containing null values (or, in the case of String fields,
837     * empty String values) in one or more fields in which non-empty
838     * values are required.
839     *
840     * This is a test of code and/or configuration in the service's
841     * validation routine(s).
842     *
843     * @param testName  The name of this test method.  This name is supplied
844     *     automatically, via reflection, by a TestNG 'data provider' in
845     *     a base class.
846  * @throws Exception 
847     */
848     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
849     dependsOnMethods = {"read"})
850     public void updateWithRequiredValuesNullOrEmpty(String testName) throws Exception {
851         // Perform setup.
852         setupUpdate(testName);
853         if (logger.isDebugEnabled()) {
854             logger.debug(testName + " got object to update with ID: " + knownResourceId);
855         }
856
857         // Read an existing record for updating.
858         ClientResponse<MultipartInput> res = updateRetrieve(testName, knownResourceId);
859
860         CollectionObjectClient client = new CollectionObjectClient();
861         MultipartInput input = (MultipartInput) res.getEntity();
862         CollectionobjectsCommon collectionObject =
863                 (CollectionobjectsCommon) extractPart(input,
864                 client.getCommonPartName(), CollectionobjectsCommon.class);
865         Assert.assertNotNull(collectionObject);
866
867         // Update with invalid content, by setting a value to the
868         // empty String, in a field that requires a non-empty value,
869         // as enforced by the service's validation routine(s).
870         collectionObject.setObjectNumber("");
871
872         if (logger.isDebugEnabled()) {
873             logger.debug(testName + " updated object");
874             logger.debug(objectAsXmlString(collectionObject,
875                     CollectionobjectsCommon.class));
876         }
877
878         // Submit the request to the service and store the response.
879         res = updateSend(testName, knownResourceId, collectionObject);
880         int statusCode = res.getStatus();
881
882         // Read the response and verify that the update attempt failed.
883         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
884                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
885         Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
886
887     }
888
889     // ---------------------------------------------------------------
890     // CRUD tests : DELETE tests
891     // ---------------------------------------------------------------
892     // Success outcomes
893     /* (non-Javadoc)
894      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#delete(java.lang.String)
895      */
896     @Override
897     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
898     dependsOnMethods = {"create", "readList", "testSubmitRequest", "update"})
899     public void delete(String testName) throws Exception {
900
901         // Perform setup.
902         setupDelete(testName);
903
904         // Submit the request to the service and store the response.
905         CollectionObjectClient client = new CollectionObjectClient();
906         ClientResponse<Response> res = client.delete(knownResourceId);
907         int statusCode = res.getStatus();
908
909         // Check the status code of the response: does it match
910         // the expected response(s)?
911         if (logger.isDebugEnabled()) {
912             logger.debug(testName + ": status = " + statusCode);
913         }
914         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
915                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
916         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
917     }
918
919     // Failure outcomes
920     /* (non-Javadoc)
921      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#deleteNonExistent(java.lang.String)
922      */
923     @Override
924     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
925     dependsOnMethods = {"delete"})
926     public void deleteNonExistent(String testName) throws Exception {
927
928         // Perform setup.
929         setupDeleteNonExistent(testName);
930
931         // Submit the request to the service and store the response.
932         CollectionObjectClient client = new CollectionObjectClient();
933         ClientResponse<Response> res = client.delete(NON_EXISTENT_ID);
934         int statusCode = res.getStatus();
935
936         // Check the status code of the response: does it match
937         // the expected response(s)?
938         if (logger.isDebugEnabled()) {
939             logger.debug(testName + ": status = " + statusCode);
940         }
941         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
942                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
943         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
944     }
945
946     // ---------------------------------------------------------------
947     // Utility tests : tests of code used in tests above
948     // ---------------------------------------------------------------
949     /**
950      * Tests the code for manually submitting data that is used by several
951      * of the methods above.
952      * @throws Exception 
953      */
954
955     @Test(dependsOnMethods = {"create", "read"})
956     public void testSubmitRequest() throws Exception {
957         testSubmitRequest(knownResourceId);
958     }
959
960     /**
961      * Test submit request.
962      *
963      * @param resourceId the resource id
964      * @throws Exception the exception
965      */
966     private void testSubmitRequest(String resourceId) throws Exception {
967
968         // Expected status code: 200 OK
969         final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
970
971         // Submit the request to the service and store the response.
972         String method = ServiceRequestType.READ.httpMethodName();
973         String url = getResourceURL(resourceId);
974         int statusCode = submitRequest(method, url);
975
976         // Check the status code of the response: does it match
977         // the expected response(s)?
978         if (logger.isDebugEnabled()) {
979             logger.debug("testSubmitRequest: url=" + url
980                     + " status=" + statusCode);
981         }
982         Assert.assertEquals(statusCode, EXPECTED_STATUS);
983
984     }
985
986     // ---------------------------------------------------------------
987     // Cleanup of resources created during testing
988     // ---------------------------------------------------------------
989     /**
990      * Deletes all resources created by tests, after all tests have been run.
991      *
992      * This cleanup method will always be run, even if one or more tests fail.
993      * For this reason, it attempts to remove all resources created
994      * at any point during testing, even if some of those resources
995      * may be expected to be deleted by certain tests.
996      */
997     @AfterClass(alwaysRun = true)
998     public void cleanUp() {
999         String noTest = System.getProperty("noTestCleanup");
1000         if(Boolean.TRUE.toString().equalsIgnoreCase(noTest)) {
1001             if (logger.isDebugEnabled()) {
1002                 logger.debug("Skipping Cleanup phase ...");
1003             }
1004             return;
1005         }
1006         if (logger.isDebugEnabled()) {
1007             logger.debug("Cleaning up temporary resources created for testing ...");
1008         }
1009        CollectionObjectClient client = new CollectionObjectClient();
1010        for (String resourceId : allResourceIdsCreated) {
1011             // Note: Any non-success responses are ignored and not reported.
1012             ClientResponse<Response> res = client.delete(resourceId);
1013         }
1014     }
1015
1016     // ---------------------------------------------------------------
1017     // Utility methods used by tests above
1018     // ---------------------------------------------------------------
1019     /**
1020      * Creates the collection object instance.
1021      *
1022      * @param commonPartName the common part name
1023      * @param identifier the identifier
1024      * @return the multipart output
1025      */
1026     private MultipartOutput createCollectionObjectInstance(String commonPartName,
1027             String identifier) {
1028         return createCollectionObjectInstance(commonPartName,
1029                 "objectNumber-" + identifier,
1030                 "objectName-" + identifier);
1031     }
1032
1033     /**
1034      * Creates the collection object instance.
1035      *
1036      * @param commonPartName the common part name
1037      * @param objectNumber the object number
1038      * @param objectName the object name
1039      * @return the multipart output
1040      */
1041     private MultipartOutput createCollectionObjectInstance(String commonPartName,
1042             String objectNumber, String objectName) {
1043         CollectionobjectsCommon collectionObject = new CollectionobjectsCommon();
1044         ResponsibleDepartmentList deptList = new ResponsibleDepartmentList();
1045         List<String> depts = deptList.getResponsibleDepartment();
1046         // @TODO Use properly formatted refNames for representative departments
1047         // in this example test record. The following are mere placeholders.
1048         depts.add("urn:org.collectionspace.services.department:Registrar");
1049         if (multivalue) {
1050             depts.add("urn:org.walkerart.department:Fine Art");
1051         }
1052         multivalue = !multivalue;
1053         //FIXME: Title does not need to be set.
1054         collectionObject.setTitle("atitle");
1055         collectionObject.setResponsibleDepartments(deptList);
1056         collectionObject.setObjectNumber(objectNumber);
1057         collectionObject.setOtherNumber("urn:org.walkerart.id:123");
1058         collectionObject.setObjectName(objectName);
1059         collectionObject.setAge(""); //test for null string
1060         collectionObject.setBriefDescription("Papier mache bird cow mask with horns, "
1061                 + "painted red with black and yellow spots. "
1062                 + "Puerto Rico. ca. 8&quot; high, 6&quot; wide, projects 10&quot; (with horns).");
1063
1064         CollectionobjectsNaturalhistory conh = new CollectionobjectsNaturalhistory();
1065         conh.setNhString("test-string");
1066         conh.setNhInt(999);
1067         conh.setNhLong(9999);
1068
1069
1070         MultipartOutput multipart = createCollectionObjectInstance(commonPartName, collectionObject, conh);
1071         return multipart;
1072     }
1073
1074     /**
1075      * Creates the collection object instance.
1076      *
1077      * @param commonPartName the common part name
1078      * @param collectionObject the collection object
1079      * @param conh the conh
1080      * @return the multipart output
1081      */
1082     private MultipartOutput createCollectionObjectInstance(String commonPartName,
1083             CollectionobjectsCommon collectionObject, CollectionobjectsNaturalhistory conh) {
1084
1085         MultipartOutput multipart = new MultipartOutput();
1086         OutputPart commonPart = multipart.addPart(collectionObject,
1087                 MediaType.APPLICATION_XML_TYPE);
1088         commonPart.getHeaders().add("label", commonPartName);
1089
1090         if (logger.isDebugEnabled()) {
1091             logger.debug("to be created, collectionobject common");
1092             logger.debug(objectAsXmlString(collectionObject,
1093                     CollectionobjectsCommon.class));
1094         }
1095
1096         if (conh != null) {
1097             OutputPart nhPart = multipart.addPart(conh, MediaType.APPLICATION_XML_TYPE);
1098             nhPart.getHeaders().add("label", getNHPartName());
1099
1100             if (logger.isDebugEnabled()) {
1101                 logger.debug("to be created, collectionobject nhistory");
1102                 logger.debug(objectAsXmlString(conh,
1103                         CollectionobjectsNaturalhistory.class));
1104             }
1105         }
1106         return multipart;
1107
1108     }
1109
1110     /**
1111      * createCollectionObjectInstanceFromXml uses JAXB unmarshaller to retrieve
1112      * collectionobject from given file
1113      * @param commonPartName
1114      * @param commonPartFileName
1115      * @return
1116      * @throws Exception
1117      */
1118     private MultipartOutput createCollectionObjectInstanceFromXml(String testName, String commonPartName,
1119             String commonPartFileName) throws Exception {
1120
1121         CollectionobjectsCommon collectionObject =
1122                 (CollectionobjectsCommon) getObjectFromFile(CollectionobjectsCommon.class,
1123                 commonPartFileName);
1124         MultipartOutput multipart = new MultipartOutput();
1125         OutputPart commonPart = multipart.addPart(collectionObject,
1126                 MediaType.APPLICATION_XML_TYPE);
1127         commonPart.getHeaders().add("label", commonPartName);
1128
1129         if (logger.isDebugEnabled()) {
1130             logger.debug(testName + " to be created, collectionobject common");
1131             logger.debug(objectAsXmlString(collectionObject,
1132                     CollectionobjectsCommon.class));
1133         }
1134         return multipart;
1135
1136     }
1137
1138     /**
1139      * createCollectionObjectInstanceFromRawXml uses stringified collectionobject
1140      * retrieve from given file
1141      * @param commonPartName
1142      * @param commonPartFileName
1143      * @return
1144      * @throws Exception
1145      */
1146     private MultipartOutput createCollectionObjectInstanceFromRawXml(String testName, String commonPartName,
1147             String commonPartFileName) throws Exception {
1148
1149         MultipartOutput multipart = new MultipartOutput();
1150         String stringObject = getXmlDocumentAsString(commonPartFileName);
1151         if (logger.isDebugEnabled()) {
1152             logger.debug(testName + " to be created, collectionobject common " + "\n" + stringObject);
1153         }
1154         OutputPart commonPart = multipart.addPart(stringObject,
1155                 MediaType.APPLICATION_XML_TYPE);
1156         commonPart.getHeaders().add("label", commonPartName);
1157
1158         return multipart;
1159
1160     }
1161
1162     /**
1163      * Gets the nH part name.
1164      *
1165      * @return the nH part name
1166      */
1167     private String getNHPartName() {
1168         return "collectionobjects_naturalhistory";
1169     }
1170
1171     /**
1172      * Creates the from xml file.
1173      *
1174      * @param testName the test name
1175      * @param fileName the file name
1176      * @param useJaxb the use jaxb
1177      * @return the string
1178      * @throws Exception the exception
1179      */
1180     private String createFromXmlFile(String testName, String fileName, boolean useJaxb) throws Exception {
1181         // Perform setup, such as initializing the type of service request
1182         // (e.g. CREATE, DELETE), its valid and expected status codes, and
1183         // its associated HTTP method name (e.g. POST, DELETE).
1184         setupCreate(testName);
1185
1186         MultipartOutput multipart = null;
1187
1188         CollectionObjectClient client = new CollectionObjectClient();
1189         if (useJaxb) {
1190             multipart = createCollectionObjectInstanceFromXml(testName,
1191                     client.getCommonPartName(), fileName);
1192         } else {
1193             multipart = createCollectionObjectInstanceFromRawXml(testName,
1194                     client.getCommonPartName(), fileName);
1195         }
1196         ClientResponse<Response> res = client.create(multipart);
1197         int statusCode = res.getStatus();
1198
1199         if (logger.isDebugEnabled()) {
1200             logger.debug(testName + ": status = " + statusCode);
1201         }
1202         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
1203                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
1204         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
1205         String newId = extractId(res);
1206         allResourceIdsCreated.add(newId);
1207         return newId;
1208     }
1209 }