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