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