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