]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
3de64ba69eecb16da5c3668798f81a2788be66e7
[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.List;
26 import javax.ws.rs.core.MediaType;
27 import javax.ws.rs.core.Response;
28
29 //import org.collectionspace.services.client.AbstractServiceClientImpl;
30 import org.collectionspace.services.client.CollectionObjectClient;
31 import org.collectionspace.services.client.CollectionObjectFactory;
32 import org.collectionspace.services.client.CollectionSpaceClient;
33 import org.collectionspace.services.collectionobject.BriefDescriptionList;
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.collectionobject.DimensionGroup;
39 import org.collectionspace.services.collectionobject.DimensionList;
40 import org.collectionspace.services.collectionobject.ObjectNameGroup;
41 import org.collectionspace.services.collectionobject.ObjectNameList;
42 import org.collectionspace.services.collectionobject.OtherNumber;
43 import org.collectionspace.services.collectionobject.OtherNumberList;
44
45 import org.collectionspace.services.jaxb.AbstractCommonList;
46
47 import org.jboss.resteasy.client.ClientResponse;
48 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
49 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
50 import org.jboss.resteasy.plugins.providers.multipart.OutputPart;
51 import org.testng.Assert;
52 import org.testng.annotations.Test;
53
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
56
57 /**
58  * CollectionObjectServiceTest, carries out tests against a
59  * deployed and running CollectionObject Service.
60  *
61  * $LastChangedRevision$
62  * $LastChangedDate$
63  */
64 public class CollectionObjectServiceTest extends AbstractServiceTestImpl {
65
66     /** The logger. */
67     private final String CLASS_NAME = CollectionObjectServiceTest.class.getName();
68     private final Logger logger = LoggerFactory.getLogger(CLASS_NAME);
69     
70     // Instance variables specific to this test.
71     /** The known resource id. */
72     private String knownResourceId = null;
73
74     private final String OBJECT_NAME_VALUE = "an object name";
75     private final String UPDATED_MEASURED_PART_VALUE = "updated measured part value";
76     private final String UTF8_TITLE = "Audiorecording album cover signed by Lech "
77             + "Wa" + '\u0142' + '\u0119' + "sa";
78
79     /* (non-Javadoc)
80      * @see org.collectionspace.services.client.test.BaseServiceTest#getServicePathComponent()
81      */
82     @Override
83     protected String getServicePathComponent() {
84         return new CollectionObjectClient().getServicePathComponent();
85     }
86     
87     /* (non-Javadoc)
88      * @see org.collectionspace.services.client.test.BaseServiceTest#getClientInstance()
89      */
90     @Override
91     protected CollectionSpaceClient getClientInstance() {
92         return new CollectionObjectClient();
93     }
94     
95     /* (non-Javadoc)
96      * @see org.collectionspace.services.client.test.BaseServiceTest#getAbstractCommonList(org.jboss.resteasy.client.ClientResponse)
97      */
98     @Override
99         protected AbstractCommonList getAbstractCommonList(
100                         ClientResponse<AbstractCommonList> response) {
101         return response.getEntity(CollectionobjectsCommonList.class);
102     }
103  
104     // ---------------------------------------------------------------
105     // CRUD tests : CREATE tests
106     // ---------------------------------------------------------------
107     // Success outcomes
108     /* (non-Javadoc)
109      * @see org.collectionspace.services.client.test.ServiceTest#create(java.lang.String)
110      */
111     @Override
112     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
113     public void create(String testName) throws Exception {
114
115         if (logger.isDebugEnabled()) {
116             logger.debug(testBanner(testName, CLASS_NAME));
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();
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     * Tests to diagnose and fix CSPACE-2242.
179     *
180     * This is a bug identified in release 0.8 in which value instances of a
181     * repeatable field are not stored when the first value instance of that
182     * field is blank.
183     */
184
185     // Verify that record creation occurs successfully when the first value instance
186     // of a single, repeatable String scalar field is non-blank.
187     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
188         dependsOnMethods = {"create", "testSubmitRequest"}, groups = {"cspace2242group"})
189     public void createFromXmlNonBlankFirstValueInstance(String testName) throws Exception {
190         if (logger.isDebugEnabled()) {
191             logger.debug(testBanner(testName, CLASS_NAME));
192         }
193         String newId =
194             createFromXmlFile(testName, "./test-data/cspace-2242-first-value-instance-nonblank.xml", true);
195         CollectionobjectsCommon collectionObject = readCollectionObjectCommonPart(newId);
196         // Verify that at least one value instance of the repeatable field was successfully persisted.
197         BriefDescriptionList descriptionList = collectionObject.getBriefDescriptions();
198         List<String> descriptions = descriptionList.getBriefDescription();
199         Assert.assertTrue(descriptions.size() > 0);
200     }
201
202     // Verify that record creation occurs successfully when the first value instance
203     // of a single, repeatable String scalar field is blank.
204     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
205         dependsOnMethods = {"create", "testSubmitRequest"}, groups = {"cspace2242group"})
206     public void createFromXmlBlankFirstValueInstance(String testName) throws Exception {
207         if (logger.isDebugEnabled()) {
208             logger.debug(testBanner(testName, CLASS_NAME));
209         }
210         String newId =
211             createFromXmlFile(testName, "./test-data/cspace-2242-first-value-instance-blank.xml", true);
212         CollectionobjectsCommon collectionObject = readCollectionObjectCommonPart(newId);
213         // Verify that at least one value instance of the repeatable field was successfully persisted.
214         BriefDescriptionList descriptionList = collectionObject.getBriefDescriptions();
215         List<String> descriptions = descriptionList.getBriefDescription();
216         Assert.assertTrue(descriptions.size() > 0);
217     }
218
219     /**
220      * Creates the from xml rfw s1.
221      *
222      * @param testName the test name
223      * @throws Exception the exception
224      */
225     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
226         dependsOnMethods = {"create", "testSubmitRequest"})
227     public void createFromXmlRFWS1(String testName) throws Exception {
228         String testDataDir = System.getProperty("test-data.fileName");
229         String newId =
230             //createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp1.xml", false);
231                 createFromXmlFile(testName, testDataDir + "/repfield_whitesp1.xml", false);
232         testSubmitRequest(newId);
233     }
234
235     /**
236      * Creates the from xml rfw s2.
237      *
238      * @param testName the test name
239      * @throws Exception the exception
240      */
241     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
242         dependsOnMethods = {"create", "testSubmitRequest"})
243     public void createFromXmlRFWS2(String testName) throws Exception {
244         String testDataDir = System.getProperty("test-data.fileName");
245         String newId =
246             //createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp2.xml", false);
247                 createFromXmlFile(testName, testDataDir + "/repfield_whitesp2.xml", false);
248         testSubmitRequest(newId);
249     }
250
251     /**
252      * Creates the from xml rfw s3.
253      *
254      * @param testName the test name
255      * @throws Exception the exception
256      */
257     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
258         dependsOnMethods = {"create", "testSubmitRequest"})
259     public void createFromXmlRFWS3(String testName) throws Exception {
260         String testDataDir = System.getProperty("test-data.fileName");
261         String newId =
262             //createFromXmlFile(testName, "./target/test-classes/test-data/repfield_whitesp3.xml", false);
263                 createFromXmlFile(testName, testDataDir + "/repfield_whitesp3.xml", false);
264         testSubmitRequest(newId);
265     }
266
267     /**
268      * Creates the from xml rfw s4.
269      *
270      * @param testName the test name
271      * @throws Exception the exception
272      */
273     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
274         dependsOnMethods = {"create", "testSubmitRequest"})
275     public void createFromXmlRFWS4(String testName) throws Exception {
276         String testDataDir = System.getProperty("test-data.fileName");
277         String newId =
278             createFromXmlFile(testName, testDataDir + "/repfield_whitesp4.xml", false);
279         testSubmitRequest(newId);
280     }
281
282     /*
283      * Tests to diagnose and verify the fixed status of CSPACE-1248,
284      * "Wedged records created!" (i.e. records with child repeatable
285      * fields, which contain null values, can be successfully created
286      * but an error occurs on trying to retrieve those records).
287      */
288
289     /**
290      * Creates a CollectionObject resource with a null value repeatable field.
291      *
292      * @param testName the test name
293      * @throws Exception the exception
294      */
295     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
296         dependsOnMethods = {"create", "testSubmitRequest"})
297     public void createWithNullValueRepeatableField(String testName) throws Exception {
298         String testDataDir = System.getProperty("test-data.fileName");
299         String newId =
300             createFromXmlFile(testName, testDataDir + "/repfield_null1.xml", false);
301         if (logger.isDebugEnabled()) {
302             logger.debug("Successfully created record with null value repeatable field.");
303             logger.debug("Attempting to retrieve just-created record ...");
304         }
305         testSubmitRequest(newId);
306     }
307
308     /**
309      * Creates a CollectionObject resource, one of whose fields contains
310      * non-Latin 1 Unicode UTF-8 characters.
311      *
312      * @param testName the test name
313      * @throws Exception the exception
314      */
315  /*
316     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
317         dependsOnMethods = {"create", "testSubmitRequest"}, groups={"utf8-create"})
318     public void createWithUTF8Title(String testName) throws Exception {
319         String testDataDir = System.getProperty("test-data.fileName");
320         String newId =
321             createFromXmlFile(testName, testDataDir + "/cspace-2779-utf-8-create.xml", false);
322         if (logger.isDebugEnabled()) {
323             logger.debug("Created record with UTF-8 chars in payload.");
324             logger.debug("Attempting to retrieve just-created record ...");
325         }
326         CollectionobjectsCommon collectionObject = readCollectionObjectCommonPart(newId);
327         String title = collectionObject.getTitle();
328         if (logger.isDebugEnabled()) {
329             logger.debug("Sent title: " + UTF8_TITLE);
330             logger.debug("Received title: " + title);
331         }
332         Assert.assertTrue(title.equals(UTF8_TITLE));
333     }
334  */
335
336     /* (non-Javadoc)
337      * @see org.collectionspace.services.client.test.ServiceTest#createList()
338      */
339     @Override
340     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
341     dependsOnMethods = {"create"})
342     public void createList(String testName) throws Exception {
343         this.createPaginatedList(testName, DEFAULT_LIST_SIZE);
344     }
345
346     // Failure outcomes
347     // Placeholders until the three tests below can be uncommented.
348     // See Issue CSPACE-401.
349     /* (non-Javadoc)
350      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#createWithEmptyEntityBody(java.lang.String)
351      */
352     @Override
353     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
354     public void createWithEmptyEntityBody(String testName) throws Exception {
355         //FIXME: Should this test really be empty?
356     }
357
358    /**
359     * Test how the service handles XML that is not well formed,
360     * when sent in the payload of a Create request.
361     *
362     * @param testName  The name of this test method.  This name is supplied
363     *     automatically, via reflection, by a TestNG 'data provider' in
364     *     a base class.
365     */
366     @Override
367     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
368     public void createWithMalformedXml(String testName) throws Exception {
369     }
370
371     /* (non-Javadoc)
372      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#createWithWrongXmlSchema(java.lang.String)
373      */
374     @Override
375     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
376     public void createWithWrongXmlSchema(String testName) throws Exception {
377         //FIXME: Should this test really be empty?
378     }
379
380
381 /*
382     @Override
383     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
384     dependsOnMethods = {"create", "testSubmitRequest"})
385     public void createWithEmptyEntityBody(String testName) throwsException {
386
387         if (logger.isDebugEnabled()) {
388             logger.debug(testBanner(testName, CLASS_NAME));
389         }
390         // Perform setup.
391         setupCreateWithEmptyEntityBody();
392
393         // Submit the request to the service and store the response.
394         String method = REQUEST_TYPE.httpMethodName();
395         String url = getServiceRootURL();
396         String mediaType = MediaType.APPLICATION_XML;
397         final String entity = "";
398         int statusCode = submitRequest(method, url, mediaType, entity);
399
400         // Check the status code of the response: does it match
401         // the expected response(s)?
402         if(logger.isDebugEnabled()){
403         logger.debug(testName + ": url=" + url +
404         " status=" + statusCode);
405         }
406         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
407         invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
408         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
409     }
410
411     @Override
412     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
413     dependsOnMethods = {"create", "testSubmitRequest"})
414     public void createWithMalformedXml(String testName) throws Exception {
415
416         if (logger.isDebugEnabled()) {
417             logger.debug(testBanner(testName, CLASS_NAME));
418         }
419         // Perform setup.
420         setupCreateWithMalformedXml();
421
422         // Submit the request to the service and store the response.
423         String method = REQUEST_TYPE.httpMethodName();
424         String url = getServiceRootURL();
425         String mediaType = MediaType.APPLICATION_XML;
426         final String entity = MALFORMED_XML_DATA; // Constant from base class.
427         int statusCode = submitRequest(method, url, mediaType, entity);
428
429         // Check the status code of the response: does it match
430         // the expected response(s)?
431         if(logger.isDebugEnabled()){
432         logger.debug(testName + ": url=" + url +
433         " status=" + statusCode);
434         }
435         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
436         invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
437         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
438     }
439
440     @Override
441     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
442     dependsOnMethods = {"create", "testSubmitRequest"})
443     public void createWithWrongXmlSchema(String testName) throws Exception {
444
445         if (logger.isDebugEnabled()) {
446             logger.debug(testBanner(testName, CLASS_NAME));
447         }
448         // Perform setup.
449         setupCreateWithWrongXmlSchema();
450
451         // Submit the request to the service and store the response.
452         String method = REQUEST_TYPE.httpMethodName();
453         String url = getServiceRootURL();
454         String mediaType = MediaType.APPLICATION_XML;
455         final String entity = WRONG_XML_SCHEMA_DATA;
456         int statusCode = submitRequest(method, url, mediaType, entity);
457
458         // Check the status code of the response: does it match
459         // the expected response(s)?
460         if(logger.isDebugEnabled()){
461         logger.debug(testName + ": url=" + url +
462         " status=" + statusCode);
463         }
464         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
465         invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
466         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
467     }
468 */
469
470    /**
471     * Test how the service handles, in a Create request, payloads
472     * containing null values (or, in the case of String fields,
473     * empty String values) in one or more fields which must be
474     * present and are required to contain non-empty values.
475     *
476     * This is a test of code and/or configuration in the service's
477     * validation routine(s).
478     *
479     * @param testName  The name of this test method.  This name is supplied
480     *     automatically, via reflection, by a TestNG 'data provider' in
481     *     a base class.
482     * @throws Exception 
483     */
484     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
485     public void createWithRequiredValuesNullOrEmpty(String testName) throws Exception {
486         if (logger.isDebugEnabled()) {
487             logger.debug(testBanner(testName, CLASS_NAME));
488         }
489         setupCreate();
490
491         // Build a payload with invalid content, by omitting a
492         // field (objectNumber) which must be present, and in which
493         // a non-empty value is required, as enforced by the service's
494         // validation routine(s).
495         CollectionobjectsCommon collectionObject = new CollectionobjectsCommon();
496         collectionObject.setTitle("a title");
497
498         ObjectNameList objNameList = new ObjectNameList();
499         List<ObjectNameGroup> objNameGroups = objNameList.getObjectNameGroup();
500         ObjectNameGroup objectNameGroup = new ObjectNameGroup();
501         objectNameGroup.setObjectName("an object name");
502         objNameGroups.add(objectNameGroup);
503         collectionObject.setObjectNameList(objNameList);
504
505         // Submit the request to the service and store the response.
506         CollectionObjectClient client = new CollectionObjectClient();
507         MultipartOutput multipart =
508                 createCollectionObjectInstance(client.getCommonPartName(), collectionObject, null);
509         ClientResponse<Response> res = client.create(multipart);
510         int statusCode = res.getStatus();
511
512         // Read the response and verify that the create attempt failed.
513         if (logger.isDebugEnabled()) {
514             logger.debug(testName + ": status = " + statusCode);
515         }
516         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
517                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
518         Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
519
520         // FIXME: Consider splitting off the following into its own test method.
521         
522         // Build a payload with invalid content, by setting a value to the
523         // empty String, in a field that requires a non-empty value,
524         // as enforced by the service's validation routine(s).
525         collectionObject = new CollectionobjectsCommon();
526         collectionObject.setObjectNumber("");
527         collectionObject.setTitle("a title");
528         objNameList = new ObjectNameList();
529         objNameGroups = objNameList.getObjectNameGroup();
530         objectNameGroup = new ObjectNameGroup();
531         objectNameGroup.setObjectName(OBJECT_NAME_VALUE);
532         objNameGroups.add(objectNameGroup);
533         collectionObject.setObjectNameList(objNameList);
534
535         // Submit the request to the service and store the response.
536         multipart =
537             createCollectionObjectInstance(client.getCommonPartName(), collectionObject, null);
538         res = client.create(multipart);
539         statusCode = res.getStatus();
540
541         // Read the response and verify that the create attempt failed.
542         if (logger.isDebugEnabled()) {
543             logger.debug(testName + ": status = " + statusCode);
544         }
545         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
546                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
547         Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
548
549     }
550
551
552     // ---------------------------------------------------------------
553     // CRUD tests : READ tests
554     // ---------------------------------------------------------------
555     // Success outcomes
556     /* (non-Javadoc)
557      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#read(java.lang.String)
558      */
559     @Override
560     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
561     dependsOnMethods = {"create"})
562     public void read(String testName) throws Exception {
563
564         if (logger.isDebugEnabled()) {
565             logger.debug(testBanner(testName, CLASS_NAME));
566         }
567         // Perform setup.
568         setupRead();
569
570         // Submit the request to the service and store the response.
571         CollectionObjectClient client = new CollectionObjectClient();
572         ClientResponse<MultipartInput> res = client.read(knownResourceId);
573         int statusCode = res.getStatus();
574
575         // Check the status code of the response: does it match
576         // the expected response(s)?
577         if (logger.isDebugEnabled()) {
578             logger.debug(testName + ": status = " + statusCode);
579         }
580         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
581                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
582         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
583
584         MultipartInput input = (MultipartInput) res.getEntity();
585
586         if (logger.isDebugEnabled()) {
587             logger.debug(testName + ": Reading Common part ...");
588         }
589         CollectionobjectsCommon collectionObject =
590                 (CollectionobjectsCommon) extractPart(input,
591                 client.getCommonPartName(), CollectionobjectsCommon.class);
592         Assert.assertNotNull(collectionObject);
593
594         // Verify the number and contents of values in repeatable fields,
595         // as created in the instance record used for testing.
596         DimensionList dimensionList = collectionObject.getDimensions();
597         Assert.assertNotNull(dimensionList);
598         List<DimensionGroup> dimensionsGroups = dimensionList.getDimensionGroup();
599         Assert.assertNotNull(dimensionsGroups);
600         Assert.assertTrue(dimensionsGroups.size() > 0);
601         Assert.assertNotNull(dimensionsGroups.get(0));
602         Assert.assertNotNull(dimensionsGroups.get(0).getMeasuredPart());
603
604         if (logger.isDebugEnabled()) {
605             logger.debug(testName + ": Reading Natural History part ...");
606         }
607         CollectionobjectsNaturalhistory conh =
608                 (CollectionobjectsNaturalhistory) extractPart(input,
609                 getNHPartName(), CollectionobjectsNaturalhistory.class);
610         Assert.assertNotNull(conh);
611     }
612
613     // Failure outcomes
614     /* (non-Javadoc)
615      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#readNonExistent(java.lang.String)
616      */
617     @Override
618     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
619     dependsOnMethods = {"read"})
620     public void readNonExistent(String testName) throws Exception {
621
622         if (logger.isDebugEnabled()) {
623             logger.debug(testBanner(testName, CLASS_NAME));
624         }
625         // Perform setup.
626         setupReadNonExistent();
627
628         // Submit the request to the service and store the response.
629         CollectionObjectClient client = new CollectionObjectClient();
630         ClientResponse<MultipartInput> res = client.read(NON_EXISTENT_ID);
631         int statusCode = res.getStatus();
632
633         // Check the status code of the response: does it match
634         // the expected response(s)?
635         if (logger.isDebugEnabled()) {
636             logger.debug(testName + ": status = " + statusCode);
637         }
638         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
639                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
640         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
641     }
642
643     
644     // ---------------------------------------------------------------
645     // CRUD tests : READ_LIST tests
646     // ---------------------------------------------------------------
647     // Success outcomes
648     /* (non-Javadoc)
649      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#readList(java.lang.String)
650      */
651     @Override
652     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
653     dependsOnMethods = {"createList", "read"})
654     public void readList(String testName) throws Exception {
655
656         if (logger.isDebugEnabled()) {
657             logger.debug(testBanner(testName, CLASS_NAME));
658         }
659         // Perform setup.
660         setupReadList();
661
662         // Submit the request to the service and store the response.
663         CollectionObjectClient client = new CollectionObjectClient();
664         ClientResponse<CollectionobjectsCommonList> res = client.readList();
665         CollectionobjectsCommonList list = res.getEntity();
666         int statusCode = res.getStatus();
667
668         // Check the status code of the response: does it match
669         // the expected response(s)?
670         if (logger.isDebugEnabled()) {
671             logger.debug(testName + ": status = " + statusCode);
672         }
673         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
674                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
675         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
676
677         // Optionally output additional data about list members for debugging.
678         boolean iterateThroughList = false;
679         if (iterateThroughList && logger.isDebugEnabled()) {
680             List<CollectionobjectsCommonList.CollectionObjectListItem> items =
681                     list.getCollectionObjectListItem();
682             int i = 0;
683
684             for (CollectionobjectsCommonList.CollectionObjectListItem item : items) {
685                 logger.debug(testName + ": list-item[" + i + "] csid="
686                         + item.getCsid());
687                 logger.debug(testName + ": list-item[" + i + "] objectNumber="
688                         + item.getObjectNumber());
689                 logger.debug(testName + ": list-item[" + i + "] URI="
690                         + item.getUri());
691                 i++;
692
693             }
694         }
695     }
696
697     // Failure outcomes
698     // None at present.
699     // ---------------------------------------------------------------
700     // CRUD tests : UPDATE tests
701     // ---------------------------------------------------------------
702     // Success outcomes
703     /* (non-Javadoc)
704      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#update(java.lang.String)
705      */
706     @Override
707     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
708     dependsOnMethods = {"read"})
709     public void update(String testName) throws Exception {
710
711         if (logger.isDebugEnabled()) {
712             logger.debug(testBanner(testName, CLASS_NAME));
713         }
714         // Perform setup.
715         setupUpdate();
716
717         // Read an existing resource that will be updated.
718         ClientResponse<MultipartInput> res = updateRetrieve(testName, knownResourceId);
719
720         // Extract its common part.
721         CollectionObjectClient client = new CollectionObjectClient();
722         MultipartInput input = (MultipartInput) res.getEntity();
723         CollectionobjectsCommon collectionObject =
724                 (CollectionobjectsCommon) extractPart(input,
725                 client.getCommonPartName(), CollectionobjectsCommon.class);
726         Assert.assertNotNull(collectionObject);
727
728         // Change the content of one or more fields in the common part.
729
730         collectionObject.setObjectNumber("updated-" + collectionObject.getObjectNumber());
731
732         // Change the object name in the first value instance in the
733         // object name repeatable group.
734         ObjectNameList objNameList = collectionObject.getObjectNameList();
735         List<ObjectNameGroup> objNameGroups = objNameList.getObjectNameGroup();
736         Assert.assertNotNull(objNameGroups);
737         Assert.assertTrue(objNameGroups.size() >= 1);
738         String objectName = objNameGroups.get(0).getObjectName();
739         Assert.assertEquals(objectName, OBJECT_NAME_VALUE);
740         String updatedObjectName = "updated-" + objectName;
741         objNameGroups.get(0).setObjectName(updatedObjectName);
742         collectionObject.setObjectNameList(objNameList);
743
744         // Replace the existing value instances in the dimensions repeatable group
745         // with entirely new value instances, also changing the number of such instances.
746         DimensionList dimensionList = collectionObject.getDimensions();
747         Assert.assertNotNull(dimensionList);
748         List<DimensionGroup> dimensionGroups = dimensionList.getDimensionGroup();
749         Assert.assertNotNull(dimensionGroups);
750         int originalDimensionGroupSize = dimensionGroups.size();
751         Assert.assertTrue(originalDimensionGroupSize >= 1);
752
753         DimensionGroup updatedDimensionGroup = new DimensionGroup();
754         updatedDimensionGroup.setMeasuredPart(UPDATED_MEASURED_PART_VALUE);
755         dimensionGroups.clear();
756         dimensionGroups.add(updatedDimensionGroup);
757         int updatedDimensionGroupSize = dimensionGroups.size();
758         Assert.assertTrue(updatedDimensionGroupSize >= 1);
759         Assert.assertTrue(updatedDimensionGroupSize != originalDimensionGroupSize);
760         collectionObject.setDimensions(dimensionList);
761
762         if (logger.isDebugEnabled()) {
763             logger.debug("sparse update that will be sent in update request:");
764             logger.debug(objectAsXmlString(collectionObject,
765                     CollectionobjectsCommon.class));
766         }
767
768         // Send the changed resource to be updated.
769         res = updateSend(testName, knownResourceId, collectionObject);
770         int statusCode = res.getStatus();
771         // Check the status code of the response: does it match the expected response(s)?
772         if (logger.isDebugEnabled()) {
773             logger.debug(testName + ": status = " + statusCode);
774         }
775         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
776                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
777         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
778
779         // Read the response and verify that the resource was correctly updated.
780         input = (MultipartInput) res.getEntity();
781         CollectionobjectsCommon updatedCollectionObject =
782                 (CollectionobjectsCommon) extractPart(input,
783                 client.getCommonPartName(), CollectionobjectsCommon.class);
784         Assert.assertNotNull(updatedCollectionObject);
785
786         objNameList = collectionObject.getObjectNameList();
787         objNameGroups = objNameList.getObjectNameGroup();
788         Assert.assertNotNull(objNameGroups);
789         Assert.assertTrue(objNameGroups.size() >= 1);
790         Assert.assertEquals(updatedObjectName,
791                 objNameGroups.get(0).getObjectName(),
792                 "Data in updated object did not match submitted data.");
793         
794         dimensionList = collectionObject.getDimensions();
795         Assert.assertNotNull(dimensionList);
796         dimensionGroups = dimensionList.getDimensionGroup();
797         Assert.assertNotNull(dimensionGroups);
798         Assert.assertTrue(dimensionGroups.size() == updatedDimensionGroupSize);
799         Assert.assertEquals(UPDATED_MEASURED_PART_VALUE,
800                 dimensionGroups.get(0).getMeasuredPart(),
801                 "Data in updated object did not match submitted data.");
802
803     }
804
805     /**
806      * Update retrieve.
807      *
808      * @param testName the test name
809      * @param id the id
810      * @return the client response
811      */
812     private ClientResponse<MultipartInput> updateRetrieve(String testName, String id) {
813         final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
814         CollectionObjectClient client = new CollectionObjectClient();
815         ClientResponse<MultipartInput> res = client.read(id);
816         if (logger.isDebugEnabled()) {
817             logger.debug("read in updateRetrieve for " + testName + " status = " + res.getStatus());
818         }
819         Assert.assertEquals(res.getStatus(), EXPECTED_STATUS);
820         if (logger.isDebugEnabled()) {
821             logger.debug("got object to updateRetrieve for " + testName + " with ID: " + id);
822         }
823         return res;
824     }
825
826     /**
827      * Update send.
828      *
829      * @param testName the test name
830      * @param id the id
831      * @param collectionObject the collection object
832      * @return the client response
833      */
834     private ClientResponse<MultipartInput> updateSend(String testName, String id,
835             CollectionobjectsCommon collectionObject) {
836         MultipartOutput output = new MultipartOutput();
837         OutputPart commonPart = output.addPart(collectionObject, MediaType.APPLICATION_XML_TYPE);
838         CollectionObjectClient client = new CollectionObjectClient();
839         commonPart.getHeaders().add("label", client.getCommonPartName());
840         ClientResponse<MultipartInput> res = client.update(knownResourceId, output);
841         return res;
842     }
843
844     // Failure outcomes
845     // Placeholders until the three tests below can be uncommented.
846     // See Issue CSPACE-401.
847     /* (non-Javadoc)
848      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateWithEmptyEntityBody(java.lang.String)
849      */
850     @Override
851     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
852     dependsOnMethods = {"read"})
853     public void updateWithEmptyEntityBody(String testName) throws Exception {
854         //FIXME: Should this test really be empty?
855     }
856
857    /**
858     * Test how the service handles XML that is not well formed,
859     * when sent in the payload of an Update request.
860     *
861     * @param testName  The name of this test method.  This name is supplied
862     *     automatically, via reflection, by a TestNG 'data provider' in
863     *     a base class.
864     */
865     @Override
866     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
867     dependsOnMethods = {"read"})
868     public void updateWithMalformedXml(String testName) throws Exception {
869         //FIXME: Should this test really be empty?
870     }
871
872     /* (non-Javadoc)
873      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateWithWrongXmlSchema(java.lang.String)
874      */
875     @Override
876     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
877     dependsOnMethods = {"read"})
878     public void updateWithWrongXmlSchema(String testName) throws Exception {
879         //FIXME: Should this test really be empty?
880     }
881
882 /*
883     @Override
884     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
885     dependsOnMethods = {"create", "update", "testSubmitRequest"})
886     public void updateWithEmptyEntityBody(String testName) throws Exception {
887
888         if (logger.isDebugEnabled()) {
889             logger.debug(testBanner(testName, CLASS_NAME));
890         }
891         // Perform setup.
892         setupUpdateWithEmptyEntityBody();
893
894         // Submit the request to the service and store the response.
895         String method = REQUEST_TYPE.httpMethodName();
896         String url = getResourceURL(knownResourceId);
897         String mediaType = MediaType.APPLICATION_XML;
898         final String entity = "";
899         int statusCode = submitRequest(method, url, mediaType, entity);
900
901         // Check the status code of the response: does it match
902         // the expected response(s)?
903         if(logger.isDebugEnabled()){
904         logger.debug(testName + ": url=" + url +
905         " status=" + statusCode);
906         }
907         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
908         invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
909         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
910     }
911
912     @Override
913     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
914     dependsOnMethods = {"create", "update", "testSubmitRequest"})
915     public void updateWithMalformedXml() throws Exception {
916
917         if (logger.isDebugEnabled()) {
918             logger.debug(testBanner(testName, CLASS_NAME));
919         }
920         // Perform setup.
921         setupUpdateWithMalformedXml();
922
923         // Submit the request to the service and store the response.
924         String method = REQUEST_TYPE.httpMethodName();
925         String url = getResourceURL(knownResourceId);
926         final String entity = MALFORMED_XML_DATA;
927         String mediaType = MediaType.APPLICATION_XML;
928         int statusCode = submitRequest(method, url, mediaType, entity);
929
930         // Check the status code of the response: does it match
931         // the expected response(s)?
932         if(logger.isDebugEnabled()){
933         logger.debug(testName + ": url=" + url +
934         " status=" + statusCode);
935         }
936         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
937         invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
938         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
939     }
940
941     @Override
942     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
943     dependsOnMethods = {"create", "update", "testSubmitRequest"})
944     public void updateWithWrongXmlSchema(String testName) throws Exception {
945
946         if (logger.isDebugEnabled()) {
947             logger.debug(testBanner(testName, CLASS_NAME));
948         }
949         // Perform setup.
950         setupUpdateWithWrongXmlSchema();
951
952         // Submit the request to the service and store the response.
953         String method = REQUEST_TYPE.httpMethodName();
954         String url = getResourceURL(knownResourceId);
955         String mediaType = MediaType.APPLICATION_XML;
956         final String entity = WRONG_XML_SCHEMA_DATA;
957         int statusCode = submitRequest(method, url, mediaType, entity);
958
959         // Check the status code of the response: does it match
960         // the expected response(s)?
961         if(logger.isDebugEnabled()){
962         logger.debug(testName + ": url=" + url +
963         " status=" + statusCode);
964         }
965         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
966         invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
967         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
968     }
969 */
970
971     /* (non-Javadoc)
972  * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateNonExistent(java.lang.String)
973  */
974 @Override
975     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
976     dependsOnMethods = {"update", "testSubmitRequest"})
977     public void updateNonExistent(String testName) throws Exception {
978
979         if (logger.isDebugEnabled()) {
980             logger.debug(testBanner(testName, CLASS_NAME));
981         }
982         // Perform setup.
983         setupUpdateNonExistent();
984
985         // Submit the request to the service and store the response.
986         //
987         // Note: The ID used in this 'create' call may be arbitrary.
988         // The only relevant ID may be the one used in updateCollectionObject(), below.
989         CollectionObjectClient client = new CollectionObjectClient();
990         MultipartOutput multipart =
991                 createCollectionObjectInstance(client.getCommonPartName(),
992                 NON_EXISTENT_ID);
993         ClientResponse<MultipartInput> res =
994                 client.update(NON_EXISTENT_ID, multipart);
995         int statusCode = res.getStatus();
996
997         // Check the status code of the response: does it match
998         // the expected response(s)?
999         if (logger.isDebugEnabled()) {
1000             logger.debug(testName + ": status = " + statusCode);
1001         }
1002         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
1003                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
1004         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
1005     }
1006
1007    /**
1008     * Test how the service handles, in an Update request, payloads
1009     * containing null values (or, in the case of String fields,
1010     * empty String values) in one or more fields in which non-empty
1011     * values are required.
1012     *
1013     * This is a test of code and/or configuration in the service's
1014     * validation routine(s).
1015     *
1016     * @param testName  The name of this test method.  This name is supplied
1017     *     automatically, via reflection, by a TestNG 'data provider' in
1018     *     a base class.
1019  * @throws Exception 
1020     */
1021     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
1022     dependsOnMethods = {"read"})
1023     public void updateWithRequiredValuesNullOrEmpty(String testName) throws Exception {
1024   
1025         if (logger.isDebugEnabled()) {
1026             logger.debug(testBanner(testName, CLASS_NAME));
1027         }
1028         // Perform setup.
1029         setupUpdate();
1030         if (logger.isDebugEnabled()) {
1031             logger.debug(testName + " got object to update with ID: " + knownResourceId);
1032         }
1033
1034         // Read an existing record for updating.
1035         ClientResponse<MultipartInput> res = updateRetrieve(testName, knownResourceId);
1036
1037         CollectionObjectClient client = new CollectionObjectClient();
1038         MultipartInput input = (MultipartInput) res.getEntity();
1039         CollectionobjectsCommon collectionObject =
1040                 (CollectionobjectsCommon) extractPart(input,
1041                 client.getCommonPartName(), CollectionobjectsCommon.class);
1042         Assert.assertNotNull(collectionObject);
1043
1044         // Update with invalid content, by setting a value to the
1045         // empty String, in a field that requires a non-empty value,
1046         // as enforced by the service's validation routine(s).
1047         collectionObject.setObjectNumber("");
1048
1049         if (logger.isDebugEnabled()) {
1050             logger.debug(testName + " updated object");
1051             logger.debug(objectAsXmlString(collectionObject,
1052                     CollectionobjectsCommon.class));
1053         }
1054
1055         // Submit the request to the service and store the response.
1056         res = updateSend(testName, knownResourceId, collectionObject);
1057         int statusCode = res.getStatus();
1058
1059         // Read the response and verify that the update attempt failed.
1060         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
1061                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
1062         Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
1063
1064     }
1065
1066     // ---------------------------------------------------------------
1067     // CRUD tests : DELETE tests
1068     // ---------------------------------------------------------------
1069     // Success outcomes
1070     /* (non-Javadoc)
1071      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#delete(java.lang.String)
1072      */
1073     @Override
1074     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
1075     dependsOnMethods = {"create", "readList", "testSubmitRequest", "update"})
1076     public void delete(String testName) throws Exception {
1077
1078         if (logger.isDebugEnabled()) {
1079             logger.debug(testBanner(testName, CLASS_NAME));
1080         }
1081         // Perform setup.
1082         setupDelete();
1083
1084         // Submit the request to the service and store the response.
1085         CollectionObjectClient client = new CollectionObjectClient();
1086         ClientResponse<Response> res = client.delete(knownResourceId);
1087         int statusCode = res.getStatus();
1088
1089         // Check the status code of the response: does it match
1090         // the expected response(s)?
1091         if (logger.isDebugEnabled()) {
1092             logger.debug(testName + ": status = " + statusCode);
1093         }
1094         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
1095                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
1096         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
1097     }
1098
1099     // Failure outcomes
1100     /* (non-Javadoc)
1101      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#deleteNonExistent(java.lang.String)
1102      */
1103     @Override
1104     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
1105     dependsOnMethods = {"delete"})
1106     public void deleteNonExistent(String testName) throws Exception {
1107
1108         if (logger.isDebugEnabled()) {
1109             logger.debug(testBanner(testName, CLASS_NAME));
1110         }
1111         // Perform setup.
1112         setupDeleteNonExistent();
1113
1114         // Submit the request to the service and store the response.
1115         CollectionObjectClient client = new CollectionObjectClient();
1116         ClientResponse<Response> res = client.delete(NON_EXISTENT_ID);
1117         int statusCode = res.getStatus();
1118
1119         // Check the status code of the response: does it match
1120         // the expected response(s)?
1121         if (logger.isDebugEnabled()) {
1122             logger.debug(testName + ": status = " + statusCode);
1123         }
1124         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
1125                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
1126         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
1127     }
1128
1129     // ---------------------------------------------------------------
1130     // Utility tests : tests of code used in tests above
1131     // ---------------------------------------------------------------
1132     /**
1133      * Tests the code for manually submitting data that is used by several
1134      * of the methods above.
1135      * @throws Exception 
1136      */
1137
1138     @Test(dependsOnMethods = {"create", "read"})
1139     public void testSubmitRequest() throws Exception {
1140         testSubmitRequest(knownResourceId);
1141     }
1142
1143     /**
1144      * Test submit request.
1145      *
1146      * @param resourceId the resource id
1147      * @throws Exception the exception
1148      */
1149     private void testSubmitRequest(String resourceId) throws Exception {
1150
1151         // Expected status code: 200 OK
1152         final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
1153
1154         // Submit the request to the service and store the response.
1155         String method = ServiceRequestType.READ.httpMethodName();
1156         String url = getResourceURL(resourceId);
1157         int statusCode = submitRequest(method, url);
1158
1159         // Check the status code of the response: does it match
1160         // the expected response(s)?
1161         if (logger.isDebugEnabled()) {
1162             logger.debug("testSubmitRequest: url=" + url
1163                     + " status=" + statusCode);
1164         }
1165         Assert.assertEquals(statusCode, EXPECTED_STATUS);
1166
1167     }
1168
1169     // ---------------------------------------------------------------
1170     // Utility methods used by tests above
1171     // ---------------------------------------------------------------
1172     /**
1173      * Creates the collection object instance.
1174      *
1175      * @param commonPartName the common part name
1176      * @param identifier the identifier
1177      * @return the multipart output
1178      */
1179     private MultipartOutput createCollectionObjectInstance(String commonPartName,
1180             String identifier) {
1181         return createCollectionObjectInstance(commonPartName,
1182                 "objectNumber-" + identifier,
1183                 "objectName-" + identifier);
1184     }
1185
1186     /**
1187      * Creates the collection object instance.
1188      *
1189      * @param commonPartName the common part name
1190      * @param objectNumber the object number
1191      * @param objectName the object name
1192      * @return the multipart output
1193      */
1194     private MultipartOutput createCollectionObjectInstance(String commonPartName,
1195             String objectNumber, String objectName) {
1196         CollectionobjectsCommon collectionObject = new CollectionobjectsCommon();
1197
1198         //REM
1199         OtherNumber remNumber = new OtherNumber();
1200         remNumber.setNumberType("remNumber");
1201         remNumber.setNumberValue("2271966-" + System.currentTimeMillis());
1202         collectionObject.setRemNumber(remNumber);
1203         
1204         // Scalar fields
1205         collectionObject.setTitle("atitle");
1206         collectionObject.setObjectNumber(objectNumber);
1207         collectionObject.setAge(""); //test for null string
1208         
1209         // FIXME this can be removed when the repeatable other number list
1210         // is supported by the application layers
1211         collectionObject.setOtherNumber("urn:org.walkerart.id:123");
1212
1213         // Repeatable structured groups
1214
1215         ObjectNameList objNameList = new ObjectNameList();
1216         List<ObjectNameGroup> objNameGroups = objNameList.getObjectNameGroup();
1217         ObjectNameGroup objectNameGroup = new ObjectNameGroup();
1218         objectNameGroup.setObjectName(OBJECT_NAME_VALUE);
1219         objNameGroups.add(objectNameGroup);
1220         collectionObject.setObjectNameList(objNameList);
1221
1222         DimensionList dimensionList = new DimensionList();
1223         List<DimensionGroup> dimensionGroups = dimensionList.getDimensionGroup();
1224         DimensionGroup dimensionGroup1 = new DimensionGroup();
1225         dimensionGroup1.setMeasuredPart("head");
1226         dimensionGroup1.setDimension("length");
1227         dimensionGroup1.setValue("30");
1228         dimensionGroup1.setMeasurementUnit("cm");
1229         DimensionGroup dimensionGroup2 = new DimensionGroup();
1230         dimensionGroup2.setMeasuredPart("leg");
1231         dimensionGroup2.setDimension("width");
1232         dimensionGroup2.setValue("2.57");
1233         dimensionGroup2.setMeasurementUnit("m");
1234         dimensionGroup2.setValueQualifier("");  // test null string
1235         dimensionGroups.add(dimensionGroup1);
1236         dimensionGroups.add(dimensionGroup2);
1237         collectionObject.setDimensions(dimensionList);
1238
1239         // Repeatable scalar fields
1240         
1241         BriefDescriptionList descriptionList = new BriefDescriptionList();
1242         List<String> descriptions = descriptionList.getBriefDescription();
1243         descriptions.add("Papier mache bird cow mask with horns, "
1244                 + "painted red with black and yellow spots. "
1245                 + "Puerto Rico. ca. 8&quot; high, 6&quot; wide, projects 10&quot; (with horns).");
1246         descriptions.add("Acrylic rabbit mask with wings, "
1247                 + "painted red with green and aquamarine spots. "
1248                 + "Puerto Rico. ca. 8&quot; high, 6&quot; wide, projects 10&quot; (with wings).");
1249         collectionObject.setBriefDescriptions(descriptionList);
1250
1251         ResponsibleDepartmentList deptList = new ResponsibleDepartmentList();
1252         List<String> depts = deptList.getResponsibleDepartment();
1253         // @TODO Use properly formatted refNames for representative departments
1254         // in this example test record. The following are mere placeholders.
1255         depts.add("urn:org.collectionspace.services.department:Registrar");
1256         depts.add("urn:org.walkerart.department:Fine Art");
1257         collectionObject.setResponsibleDepartments(deptList);
1258
1259         OtherNumberList otherNumList = new OtherNumberList();
1260         List<OtherNumber> otherNumbers = otherNumList.getOtherNumber();
1261         OtherNumber otherNumber1 = new OtherNumber();        
1262         otherNumber1.setNumberValue("101." + objectName);
1263         otherNumber1.setNumberType("integer");
1264         otherNumbers.add(otherNumber1);
1265         OtherNumber otherNumber2 = new OtherNumber();
1266         otherNumber2.setNumberValue("101.502.23.456." + objectName);
1267         otherNumber2.setNumberType("ipaddress");
1268         otherNumbers.add(otherNumber2);
1269         collectionObject.setOtherNumberList(otherNumList);
1270
1271         // Add instances of fields from an extension schema
1272
1273         CollectionobjectsNaturalhistory conh = new CollectionobjectsNaturalhistory();
1274         conh.setNhString("test-string");
1275         conh.setNhInt(999);
1276         conh.setNhLong(9999);
1277
1278         MultipartOutput multipart = createCollectionObjectInstance(commonPartName, collectionObject, conh);
1279         return multipart;
1280     }
1281
1282     /**
1283      * Creates the collection object instance.
1284      *
1285      * @param commonPartName the common part name
1286      * @param collectionObject the collection object
1287      * @param conh the conh
1288      * @return the multipart output
1289      */
1290     private MultipartOutput createCollectionObjectInstance(String commonPartName,
1291             CollectionobjectsCommon collectionObject, CollectionobjectsNaturalhistory conh) {
1292
1293         MultipartOutput multipart = CollectionObjectFactory.createCollectionObjectInstance(
1294                 commonPartName, collectionObject, getNHPartName(), conh);
1295         if (logger.isDebugEnabled()) {
1296             logger.debug("to be created, collectionobject common");
1297             logger.debug(objectAsXmlString(collectionObject,
1298                     CollectionobjectsCommon.class));
1299         }
1300
1301         if (conh != null) {
1302             if (logger.isDebugEnabled()) {
1303                 logger.debug("to be created, collectionobject nhistory");
1304                 logger.debug(objectAsXmlString(conh,
1305                         CollectionobjectsNaturalhistory.class));
1306             }
1307         }
1308         return multipart;
1309
1310     }
1311
1312     /**
1313      * createCollectionObjectInstanceFromXml uses JAXB unmarshaller to retrieve
1314      * collectionobject from given file
1315      * @param commonPartName
1316      * @param commonPartFileName
1317      * @return
1318      * @throws Exception
1319      */
1320     private MultipartOutput createCollectionObjectInstanceFromXml(String testName, String commonPartName,
1321             String commonPartFileName) throws Exception {
1322
1323         CollectionobjectsCommon collectionObject =
1324                 (CollectionobjectsCommon) getObjectFromFile(CollectionobjectsCommon.class,
1325                 commonPartFileName);
1326         MultipartOutput multipart = new MultipartOutput();
1327         OutputPart commonPart = multipart.addPart(collectionObject,
1328                 MediaType.APPLICATION_XML_TYPE);
1329         commonPart.getHeaders().add("label", commonPartName);
1330
1331         if (logger.isDebugEnabled()) {
1332             logger.debug(testName + " to be created, collectionobject common");
1333             logger.debug(objectAsXmlString(collectionObject,
1334                     CollectionobjectsCommon.class));
1335         }
1336         return multipart;
1337
1338     }
1339
1340     /**
1341      * createCollectionObjectInstanceFromRawXml uses stringified collectionobject
1342      * retrieve from given file
1343      * @param commonPartName
1344      * @param commonPartFileName
1345      * @return
1346      * @throws Exception
1347      */
1348     private MultipartOutput createCollectionObjectInstanceFromRawXml(String testName, String commonPartName,
1349             String commonPartFileName) throws Exception {
1350
1351         MultipartOutput multipart = new MultipartOutput();
1352         String stringObject = getXmlDocumentAsString(commonPartFileName);
1353         if (logger.isDebugEnabled()) {
1354             logger.debug(testName + " to be created, collectionobject common " + "\n" + stringObject);
1355         }
1356         OutputPart commonPart = multipart.addPart(stringObject,
1357                 MediaType.APPLICATION_XML_TYPE);
1358         commonPart.getHeaders().add("label", commonPartName);
1359
1360         return multipart;
1361
1362     }
1363
1364     /**
1365      * Gets the nH part name.
1366      *
1367      * @return the nH part name
1368      */
1369     private String getNHPartName() {
1370         return "collectionobjects_naturalhistory";
1371     }
1372
1373     /**
1374      * Creates the from xml file.
1375      *
1376      * @param testName the test name
1377      * @param fileName the file name
1378      * @param useJaxb the use jaxb
1379      * @return the string
1380      * @throws Exception the exception
1381      */
1382     private String createFromXmlFile(String testName, String fileName, boolean useJaxb) throws Exception {
1383   
1384         // Perform setup.
1385         setupCreate();
1386
1387         MultipartOutput multipart = null;
1388
1389         CollectionObjectClient client = new CollectionObjectClient();
1390         if (useJaxb) {
1391             multipart = createCollectionObjectInstanceFromXml(testName,
1392                     client.getCommonPartName(), fileName);
1393         } else {
1394             multipart = createCollectionObjectInstanceFromRawXml(testName,
1395                     client.getCommonPartName(), fileName);
1396         }
1397         ClientResponse<Response> res = client.create(multipart);
1398         int statusCode = res.getStatus();
1399
1400         if (logger.isDebugEnabled()) {
1401             logger.debug(testName + ": status = " + statusCode);
1402         }
1403         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
1404                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
1405         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
1406         String newId = extractId(res);
1407         allResourceIdsCreated.add(newId);
1408         return newId;
1409     }
1410
1411     // FIXME: This duplicates code in read(), and should be consolidated.
1412     // This is an expedient to support reading and verifying the contents
1413     // of resources that have been created from test data XML files.
1414     private CollectionobjectsCommon readCollectionObjectCommonPart(String csid)
1415         throws Exception {
1416
1417         String testName = "readCollectionObjectCommonPart";
1418
1419         setupRead();
1420
1421         // Submit the request to the service and store the response.
1422         CollectionObjectClient client = new CollectionObjectClient();
1423         ClientResponse<MultipartInput> res = client.read(csid);
1424         int statusCode = res.getStatus();
1425
1426         // Check the status code of the response: does it match
1427         // the expected response(s)?
1428         if (logger.isDebugEnabled()) {
1429             logger.debug(testName + ": status = " + statusCode);
1430         }
1431         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
1432                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
1433         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
1434
1435         MultipartInput input = (MultipartInput) res.getEntity();
1436
1437         if (logger.isDebugEnabled()) {
1438             logger.debug(testName + ": Reading Common part ...");
1439         }
1440         CollectionobjectsCommon collectionObject =
1441                 (CollectionobjectsCommon) extractPart(input,
1442                 client.getCommonPartName(), CollectionobjectsCommon.class);
1443         Assert.assertNotNull(collectionObject);
1444
1445         return collectionObject;
1446      }
1447 }