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