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