]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
c550bedb33a7a7314adb29863e56a5679fd08b97
[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.text.DateFormat;
26 import java.text.SimpleDateFormat;
27 import java.util.Calendar;
28 import java.util.Date;
29 import java.util.List;
30 import java.util.TimeZone;
31 import javax.ws.rs.core.MediaType;
32 import javax.ws.rs.core.Response;
33
34 import org.collectionspace.services.common.datetime.GregorianCalendarDateTimeUtils;
35 import org.collectionspace.services.client.CollectionSpaceClient;
36 import org.collectionspace.services.client.MovementClient;
37 import org.collectionspace.services.jaxb.AbstractCommonList;
38 import org.collectionspace.services.movement.MovementsCommon;
39 import org.collectionspace.services.movement.MovementsCommonList;
40 import org.collectionspace.services.movement.MovementMethodsList;
41
42 import org.jboss.resteasy.client.ClientResponse;
43
44 import org.collectionspace.services.client.PayloadInputPart;
45 import org.collectionspace.services.client.PayloadOutputPart;
46 import org.collectionspace.services.client.PoxPayloadIn;
47 import org.collectionspace.services.client.PoxPayloadOut;
48 import org.testng.Assert;
49 import org.testng.annotations.Test;
50
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 /**
55  * MovementServiceTest, carries out tests against a
56  * deployed and running Movement Service.
57  *
58  * $LastChangedRevision$
59  * $LastChangedDate$
60  */
61 public class MovementServiceTest extends AbstractServiceTestImpl {
62
63    /** The logger. */
64     private final String CLASS_NAME = MovementServiceTest.class.getName();
65     private final Logger logger = LoggerFactory.getLogger(CLASS_NAME);
66
67     final String SERVICE_NAME = "movements";
68     final String SERVICE_PATH_COMPONENT = "movements";
69
70     // Instance variables specific to this test.
71     private String knownResourceId = null;
72     private final static String TIMESTAMP_UTC = GregorianCalendarDateTimeUtils.timestampUTC();
73     
74     /* (non-Javadoc)
75      * @see org.collectionspace.services.client.test.BaseServiceTest#getClientInstance()
76      */
77     @Override
78     protected CollectionSpaceClient getClientInstance() {
79         return new MovementClient();
80     }
81     
82     /* (non-Javadoc)
83      * @see org.collectionspace.services.client.test.BaseServiceTest#getAbstractCommonList(org.jboss.resteasy.client.ClientResponse)
84      */
85     @Override
86         protected AbstractCommonList getAbstractCommonList(
87                         ClientResponse<AbstractCommonList> response) {
88         return response.getEntity(MovementsCommonList.class);
89     }
90  
91     // ---------------------------------------------------------------
92     // CRUD tests : CREATE tests
93     // ---------------------------------------------------------------
94     // Success outcomes
95     /* (non-Javadoc)
96      * @see org.collectionspace.services.client.test.ServiceTest#create(java.lang.String)
97      */
98     @Override
99     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class)
100     public void create(String testName) throws Exception {
101
102         if (logger.isDebugEnabled()) {
103             logger.debug(testBanner(testName, CLASS_NAME));
104         }
105         // Perform setup, such as initializing the type of service request
106         // (e.g. CREATE, DELETE), its valid and expected status codes, and
107         // its associated HTTP method name (e.g. POST, DELETE).
108         setupCreate();
109
110         // Submit the request to the service and store the response.
111         MovementClient client = new MovementClient();
112         String identifier = createIdentifier();
113         PoxPayloadOut multipart = createMovementInstance(identifier);
114         ClientResponse<Response> res = client.create(multipart);
115
116         int statusCode = res.getStatus();
117
118         // Check the status code of the response: does it match
119         // the expected response(s)?
120         //
121         // Specifically:
122         // Does it fall within the set of valid status codes?
123         // Does it exactly match the expected status code?
124         if(logger.isDebugEnabled()){
125             logger.debug(testName + ": status = " + statusCode);
126         }
127         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
128                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
129         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
130
131         // Store the ID returned from the first resource created
132         // for additional tests below.
133         if (knownResourceId == null){
134             knownResourceId = extractId(res);
135             if (logger.isDebugEnabled()) {
136                 logger.debug(testName + ": knownResourceId=" + knownResourceId);
137             }
138         }
139         
140         // Store the IDs from every resource created by tests,
141         // so they can be deleted after tests have been run.
142         allResourceIdsCreated.add(extractId(res));
143     }
144
145     /* (non-Javadoc)
146      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#createList(java.lang.String)
147      */
148     @Override
149     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
150         dependsOnMethods = {"create"})
151     public void createList(String testName) throws Exception {
152         for(int i = 0; i < 3; i++){
153             create(testName);
154         }
155     }
156
157     // Failure outcomes
158     // Placeholders until the three tests below can be uncommented.
159     // See Issue CSPACE-401.
160     /* (non-Javadoc)
161      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#createWithEmptyEntityBody(java.lang.String)
162      */
163     @Override
164     public void createWithEmptyEntityBody(String testName) throws Exception {
165         //Should this really be empty?
166     }
167
168     /* (non-Javadoc)
169      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#createWithMalformedXml(java.lang.String)
170      */
171     @Override
172     public void createWithMalformedXml(String testName) throws Exception {
173         //Should this really be empty?
174     }
175
176     /* (non-Javadoc)
177      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#createWithWrongXmlSchema(java.lang.String)
178      */
179     @Override
180     public void createWithWrongXmlSchema(String testName) throws Exception {
181         //Should this really be empty?
182     }
183
184     /*
185     @Override
186     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
187         dependsOnMethods = {"create", "testSubmitRequest"})
188     public void createWithEmptyEntityBody(String testName) throws Exception {
189
190         if (logger.isDebugEnabled()) {
191             logger.debug(testBanner(testName, CLASS_NAME));
192         }
193         // Perform setup.
194         setupCreateWithEmptyEntityBody();
195
196         // Submit the request to the service and store the response.
197         String method = REQUEST_TYPE.httpMethodName();
198         String url = getServiceRootURL();
199         String mediaType = MediaType.APPLICATION_XML;
200         final String entity = "";
201         int statusCode = submitRequest(method, url, mediaType, entity);
202
203         // Check the status code of the response: does it match
204         // the expected response(s)?
205         if(logger.isDebugEnabled()){
206             logger.debug("createWithEmptyEntityBody url=" + url +
207                 " status=" + statusCode);
208          }
209         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
210         invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
211         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
212     }
213
214     @Override
215     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
216         dependsOnMethods = {"create", "testSubmitRequest"})
217     public void createWithMalformedXml(String testName) throws Exception {
218
219         if (logger.isDebugEnabled()) {
220             logger.debug(testBanner(testName, CLASS_NAME));
221         }
222         // Perform setup.
223         setupCreateWithMalformedXml();
224
225         // Submit the request to the service and store the response.
226         String method = REQUEST_TYPE.httpMethodName();
227         String url = getServiceRootURL();
228         String mediaType = MediaType.APPLICATION_XML;
229         final String entity = MALFORMED_XML_DATA; // Constant from base class.
230         int statusCode = submitRequest(method, url, mediaType, entity);
231
232         // Check the status code of the response: does it match
233         // the expected response(s)?
234         if(logger.isDebugEnabled()){
235             logger.debug(testName + ": url=" + url +
236                 " status=" + statusCode);
237          }
238         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
239         invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
240         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
241     }
242
243     @Override
244     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
245         dependsOnMethods = {"create", "testSubmitRequest"})
246     public void createWithWrongXmlSchema(String testName) throws Exception {
247
248         if (logger.isDebugEnabled()) {
249             logger.debug(testBanner(testName, CLASS_NAME));
250         }
251         // Perform setup.
252         setupCreateWithWrongXmlSchema();
253
254         // Submit the request to the service and store the response.
255         String method = REQUEST_TYPE.httpMethodName();
256         String url = getServiceRootURL();
257         String mediaType = MediaType.APPLICATION_XML;
258         final String entity = WRONG_XML_SCHEMA_DATA;
259         int statusCode = submitRequest(method, url, mediaType, entity);
260
261         // Check the status code of the response: does it match
262         // the expected response(s)?
263         if(logger.isDebugEnabled()){
264             logger.debug(testName + ": url=" + url +
265                 " status=" + statusCode);
266          }
267         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
268         invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
269         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
270     }
271      */
272
273     // ---------------------------------------------------------------
274     // CRUD tests : READ tests
275     // ---------------------------------------------------------------
276     // Success outcomes
277     /* (non-Javadoc)
278      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#read(java.lang.String)
279      */
280     @Override
281     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
282         dependsOnMethods = {"create"})
283     public void read(String testName) throws Exception {
284
285         if (logger.isDebugEnabled()) {
286             logger.debug(testBanner(testName, CLASS_NAME));
287         }
288         // Perform setup.
289         setupRead();
290
291         // Submit the request to the service and store the response.
292         MovementClient client = new MovementClient();
293         ClientResponse<String> res = client.read(knownResourceId);
294         int statusCode = res.getStatus();
295
296         // Check the status code of the response: does it match
297         // the expected response(s)?
298         if(logger.isDebugEnabled()){
299             logger.debug(testName + ": status = " + statusCode);
300         }
301         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
302                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
303         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
304
305         // Get the common part of the response and verify that it is not null.
306         PoxPayloadIn input = new PoxPayloadIn(res.getEntity());
307         PayloadInputPart payloadInputPart = input.getPart(client.getCommonPartName());
308         MovementsCommon movementCommon = null;
309         if (payloadInputPart != null) {
310                 movementCommon = (MovementsCommon) payloadInputPart.getBody();
311         }
312         Assert.assertNotNull(movementCommon);
313
314         // Check selected fields.
315
316         // Check the values of one or more date/time fields.
317         if (logger.isDebugEnabled()) {
318             logger.debug("locationDate=" + movementCommon.getLocationDate());
319             logger.debug("TIMESTAMP_UTC=" + TIMESTAMP_UTC);
320         }
321         Assert.assertTrue(movementCommon.getLocationDate().equals(TIMESTAMP_UTC));
322         Assert.assertTrue(movementCommon.getPlannedRemovalDate().equals(TIMESTAMP_UTC));
323         Assert.assertNull(movementCommon.getRemovalDate());
324         
325         // Check the values of fields containing Unicode UTF-8 (non-Latin-1) characters.
326        if(logger.isDebugEnabled()){
327             logger.debug("UTF-8 data sent=" + getUTF8DataFragment() + "\n"
328                     + "UTF-8 data received=" + movementCommon.getMovementNote());
329     }
330         Assert.assertEquals(movementCommon.getMovementNote(), getUTF8DataFragment(),
331                 "UTF-8 data retrieved '" + movementCommon.getMovementNote()
332                 + "' does not match expected data '" + getUTF8DataFragment());
333
334     }
335
336     // Failure outcomes
337     /* (non-Javadoc)
338      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#readNonExistent(java.lang.String)
339      */
340     @Override
341     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
342         dependsOnMethods = {"read"})
343     public void readNonExistent(String testName) throws Exception {
344
345         if (logger.isDebugEnabled()) {
346             logger.debug(testBanner(testName, CLASS_NAME));
347         }
348         // Perform setup.
349         setupReadNonExistent();
350
351         // Submit the request to the service and store the response.
352         MovementClient client = new MovementClient();
353         ClientResponse<String> res = client.read(NON_EXISTENT_ID);
354         int statusCode = res.getStatus();
355
356         // Check the status code of the response: does it match
357         // the expected response(s)?
358         if(logger.isDebugEnabled()){
359             logger.debug(testName + ": status = " + statusCode);
360         }
361         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
362                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
363         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
364     }
365
366     // ---------------------------------------------------------------
367     // CRUD tests : READ_LIST tests
368     // ---------------------------------------------------------------
369     // Success outcomes
370     /* (non-Javadoc)
371      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#readList(java.lang.String)
372      */
373     @Override
374     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
375         dependsOnMethods = {"createList", "read"})
376     public void readList(String testName) throws Exception {
377
378         if (logger.isDebugEnabled()) {
379             logger.debug(testBanner(testName, CLASS_NAME));
380         }
381         // Perform setup.
382         setupReadList();
383
384         // Submit the request to the service and store the response.
385         MovementClient client = new MovementClient();
386         ClientResponse<MovementsCommonList> res = client.readList();
387         MovementsCommonList list = res.getEntity();
388         int statusCode = res.getStatus();
389
390         // Check the status code of the response: does it match
391         // the expected response(s)?
392         if(logger.isDebugEnabled()){
393             logger.debug(testName + ": status = " + statusCode);
394         }
395         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
396                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
397         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
398
399         // Optionally output additional data about list members for debugging.
400         boolean iterateThroughList = true;
401         if(iterateThroughList && logger.isDebugEnabled()){
402             List<MovementsCommonList.MovementListItem> items =
403                     list.getMovementListItem();
404             int i = 0;
405             for(MovementsCommonList.MovementListItem item : items){
406                 logger.debug(testName + ": list-item[" + i + "] csid=" +
407                         item.getCsid());
408                 logger.debug(testName + ": list-item[" + i + "] movementReferenceNumber=" +
409                         item.getMovementReferenceNumber());
410                 logger.debug(testName + ": list-item[" + i + "] locationDate=" +
411                         item.getLocationDate());
412                 logger.debug(testName + ": list-item[" + i + "] URI=" +
413                         item.getUri());
414                 i++;
415             }
416         }
417
418     }
419
420     // Failure outcomes
421     // None at present.
422     // ---------------------------------------------------------------
423     // CRUD tests : UPDATE tests
424     // ---------------------------------------------------------------
425     // Success outcomes
426     /* (non-Javadoc)
427      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#update(java.lang.String)
428      */
429     @Override
430     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
431         dependsOnMethods = {"read"})
432     public void update(String testName) throws Exception {
433
434         if (logger.isDebugEnabled()) {
435             logger.debug(testBanner(testName, CLASS_NAME));
436         }
437         // Perform setup.
438         setupUpdate();
439
440         // Retrieve the contents of a resource to update.
441         MovementClient client = new MovementClient();
442         ClientResponse<String> res = client.read(knownResourceId);
443         if(logger.isDebugEnabled()){
444             logger.debug(testName + ": read status = " + res.getStatus());
445         }
446         Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE);
447         if(logger.isDebugEnabled()){
448             logger.debug("got object to update with ID: " + knownResourceId);
449         }
450
451         // Extract the common part from the response.
452         PoxPayloadIn input = new PoxPayloadIn(res.getEntity());
453         PayloadInputPart payloadInputPart = input.getPart(client.getCommonPartName());
454         MovementsCommon movementCommon = null;
455         if (payloadInputPart != null) {
456                 movementCommon = (MovementsCommon) payloadInputPart.getBody();
457         }
458         Assert.assertNotNull(movementCommon);
459
460         // Update its content.
461         movementCommon.setMovementReferenceNumber("updated-" + movementCommon.getMovementReferenceNumber());
462         movementCommon.setMovementNote("updated movement note-" + movementCommon.getMovementNote());
463         movementCommon.setNormalLocation(""); // Test deletion of existing string value
464
465         String currentTimestamp = GregorianCalendarDateTimeUtils.timestampUTC();
466         movementCommon.setPlannedRemovalDate(""); // Test deletion of existing date or date/time value
467         movementCommon.setRemovalDate(currentTimestamp);
468
469         if(logger.isDebugEnabled()){
470             logger.debug("to be updated object");
471             logger.debug(objectAsXmlString(movementCommon, MovementsCommon.class));
472         }
473
474         // Submit the request to the service and store the response.
475         PoxPayloadOut output = new PoxPayloadOut(this.getServicePathComponent());
476         PayloadOutputPart commonPart = output.addPart(movementCommon, MediaType.APPLICATION_XML_TYPE);
477         commonPart.setLabel(client.getCommonPartName());
478         res = client.update(knownResourceId, output);
479
480         // Check the status code of the response: does it match the expected response(s)?
481         int statusCode = res.getStatus();
482         if(logger.isDebugEnabled()){
483             logger.debug(testName + ": status = " + statusCode);
484         }
485         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
486                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
487         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
488
489        // Extract the updated common part from the response.
490         input = new PoxPayloadIn(res.getEntity());
491         payloadInputPart = input.getPart(client.getCommonPartName());
492         MovementsCommon updatedMovementCommon = null;
493         if (payloadInputPart != null) {
494                 updatedMovementCommon = (MovementsCommon) payloadInputPart.getBody();
495         }
496         Assert.assertNotNull(movementCommon);
497         if(logger.isDebugEnabled()){
498             logger.debug("updated object");
499             logger.debug(objectAsXmlString(updatedMovementCommon, MovementsCommon.class));
500         }
501
502         // Check selected fields in the updated common part.
503         Assert.assertEquals(updatedMovementCommon.getNormalLocation(),
504             movementCommon.getNormalLocation(), "Data in updated object did not match submitted data.");
505         if(logger.isDebugEnabled()){
506             logger.debug("Normal location after update=|" + updatedMovementCommon.getNormalLocation() + "|");
507         }
508
509         Assert.assertEquals(updatedMovementCommon.getMovementReferenceNumber(),
510             movementCommon.getMovementReferenceNumber(),
511             "Data in updated object did not match submitted data.");
512         Assert.assertEquals(updatedMovementCommon.getMovementNote(),
513             movementCommon.getMovementNote(),
514             "Data in updated object did not match submitted data.");
515         Assert.assertNull(updatedMovementCommon.getPlannedRemovalDate());
516         Assert.assertEquals(updatedMovementCommon.getRemovalDate(),
517             movementCommon.getRemovalDate(),
518             "Data in updated object did not match submitted data.");
519
520         if(logger.isDebugEnabled()){
521             logger.debug("UTF-8 data sent=" + movementCommon.getMovementNote() + "\n"
522                     + "UTF-8 data received=" + updatedMovementCommon.getMovementNote());
523     }
524         Assert.assertTrue(updatedMovementCommon.getMovementNote().contains(getUTF8DataFragment()),
525                 "UTF-8 data retrieved '" + updatedMovementCommon.getMovementNote()
526                 + "' does not contain expected data '" + getUTF8DataFragment());
527         Assert.assertEquals(updatedMovementCommon.getMovementNote(),
528                 movementCommon.getMovementNote(),
529                 "Data in updated object did not match submitted data.");
530
531     }
532
533     // Failure outcomes
534     // Placeholders until the three tests below can be uncommented.
535     // See Issue CSPACE-401.
536     /* (non-Javadoc)
537      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateWithEmptyEntityBody(java.lang.String)
538      */
539     @Override
540     public void updateWithEmptyEntityBody(String testName) throws Exception{
541         //Should this really be empty?
542     }
543     
544     /* (non-Javadoc)
545      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateWithMalformedXml(java.lang.String)
546      */
547     @Override
548     public void updateWithMalformedXml(String testName) throws Exception {
549         //Should this really be empty?
550     }
551     
552     /* (non-Javadoc)
553      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateWithWrongXmlSchema(java.lang.String)
554      */
555     @Override
556     public void updateWithWrongXmlSchema(String testName) throws Exception {
557         //Should this really be empty?
558     }
559
560     /*
561     @Override
562     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
563         dependsOnMethods = {"create", "update", "testSubmitRequest"})
564     public void updateWithEmptyEntityBody(String testName) throws Exception {
565
566         if (logger.isDebugEnabled()) {
567             logger.debug(testBanner(testName, CLASS_NAME));
568         }
569         // Perform setup.
570         setupUpdateWithEmptyEntityBody();
571
572         // Submit the request to the service and store the response.
573         String method = REQUEST_TYPE.httpMethodName();
574         String url = getResourceURL(knownResourceId);
575         String mediaType = MediaType.APPLICATION_XML;
576         final String entity = "";
577         int statusCode = submitRequest(method, url, mediaType, entity);
578
579         // Check the status code of the response: does it match
580         // the expected response(s)?
581         if(logger.isDebugEnabled()){
582             logger.debug(testName + ": url=" + url +
583                 " status=" + statusCode);
584          }
585         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
586         invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
587         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
588     }
589
590     @Override
591     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
592         dependsOnMethods = {"create", "update", "testSubmitRequest"})
593     public void updateWithMalformedXml(String testName) throws Exception {
594
595         if (logger.isDebugEnabled()) {
596             logger.debug(testBanner(testName, CLASS_NAME));
597         }
598         // Perform setup.
599         setupUpdateWithMalformedXml();
600
601         // Submit the request to the service and store the response.
602         String method = REQUEST_TYPE.httpMethodName();
603         String url = getResourceURL(knownResourceId);
604         String mediaType = MediaType.APPLICATION_XML;
605         final String entity = MALFORMED_XML_DATA;
606         int statusCode = submitRequest(method, url, mediaType, entity);
607
608         // Check the status code of the response: does it match
609         // the expected response(s)?
610         if(logger.isDebugEnabled()){
611             logger.debug(testName + ": url=" + url +
612              " status=" + statusCode);
613          }
614         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
615         invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
616         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
617     }
618
619     @Override
620     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
621         dependsOnMethods = {"create", "update", "testSubmitRequest"})
622     public void updateWithWrongXmlSchema(String testName) throws Exception {
623
624         if (logger.isDebugEnabled()) {
625             logger.debug(testBanner(testName, CLASS_NAME));
626         }
627         // Perform setup.
628         setupUpdateWithWrongXmlSchema();
629
630         // Submit the request to the service and store the response.
631         String method = REQUEST_TYPE.httpMethodName();
632         String url = getResourceURL(knownResourceId);
633         String mediaType = MediaType.APPLICATION_XML;
634         final String entity = WRONG_XML_SCHEMA_DATA;
635         int statusCode = submitRequest(method, url, mediaType, entity);
636
637         // Check the status code of the response: does it match
638         // the expected response(s)?
639         if(logger.isDebugEnabled()){
640             logger.debug(testName + ": url=" + url +
641             " status=" + statusCode);
642          }
643         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
644         invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
645         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
646     }
647      */
648
649     /* (non-Javadoc)
650      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#updateNonExistent(java.lang.String)
651      */
652     @Override
653     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
654         dependsOnMethods = {"update", "testSubmitRequest"})
655     public void updateNonExistent(String testName) throws Exception {
656
657         if (logger.isDebugEnabled()) {
658             logger.debug(testBanner(testName, CLASS_NAME));
659         }
660         // Perform setup.
661         setupUpdateNonExistent();
662
663         // Submit the request to the service and store the response.
664         // Note: The ID used in this 'create' call may be arbitrary.
665         // The only relevant ID may be the one used in update(), below.
666         MovementClient client = new MovementClient();
667         PoxPayloadOut multipart = createMovementInstance(NON_EXISTENT_ID);
668         ClientResponse<String> res = client.update(NON_EXISTENT_ID, multipart);
669         int statusCode = res.getStatus();
670
671         // Check the status code of the response: does it match
672         // the expected response(s)?
673         if(logger.isDebugEnabled()){
674             logger.debug(testName + ": status = " + statusCode);
675         }
676         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
677                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
678         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
679     }
680
681     // ---------------------------------------------------------------
682     // CRUD tests : DELETE tests
683     // ---------------------------------------------------------------
684     // Success outcomes
685     /* (non-Javadoc)
686      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#delete(java.lang.String)
687      */
688
689     @Override
690     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
691         dependsOnMethods = {"create", "readList", "testSubmitRequest", "update"})
692     public void delete(String testName) throws Exception {
693
694         if (logger.isDebugEnabled()) {
695             logger.debug(testBanner(testName, CLASS_NAME));
696         }
697         /*
698         // Perform setup.
699         setupDelete();
700
701         // Submit the request to the service and store the response.
702         MovementClient client = new MovementClient();
703         ClientResponse<Response> res = client.delete(knownResourceId);
704         int statusCode = res.getStatus();
705
706         // Check the status code of the response: does it match
707         // the expected response(s)?
708         if(logger.isDebugEnabled()){
709             logger.debug(testName + ": status = " + statusCode);
710         }
711         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
712                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
713         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
714      *
715      */
716     }
717
718
719     // Failure outcomes
720     /* (non-Javadoc)
721      * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#deleteNonExistent(java.lang.String)
722      */
723     @Override
724     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
725         dependsOnMethods = {"delete"})
726     public void deleteNonExistent(String testName) throws Exception {
727
728         if (logger.isDebugEnabled()) {
729             logger.debug(testBanner(testName, CLASS_NAME));
730         }
731         // Perform setup.
732         setupDeleteNonExistent();
733
734         // Submit the request to the service and store the response.
735         MovementClient client = new MovementClient();
736         ClientResponse<Response> res = client.delete(NON_EXISTENT_ID);
737         int statusCode = res.getStatus();
738
739         // Check the status code of the response: does it match
740         // the expected response(s)?
741         if(logger.isDebugEnabled()){
742             logger.debug(testName + ": status = " + statusCode);
743         }
744         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
745                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
746         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
747     }
748
749     // ---------------------------------------------------------------
750     // Utility tests : tests of code used in tests above
751     // ---------------------------------------------------------------
752     /**
753      * Tests the code for manually submitting data that is used by several
754      * of the methods above.
755      */
756     @Test(dependsOnMethods = {"create", "read"})
757     public void testSubmitRequest() {
758
759         // Expected status code: 200 OK
760         final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
761
762         // Submit the request to the service and store the response.
763         String method = ServiceRequestType.READ.httpMethodName();
764         String url = getResourceURL(knownResourceId);
765         int statusCode = submitRequest(method, url);
766
767         // Check the status code of the response: does it match
768         // the expected response(s)?
769         if(logger.isDebugEnabled()){
770             logger.debug("testSubmitRequest: url=" + url +
771                 " status=" + statusCode);
772         }
773         Assert.assertEquals(statusCode, EXPECTED_STATUS);
774
775     }
776
777     // ---------------------------------------------------------------
778     // Utility methods used by tests above
779     // ---------------------------------------------------------------
780
781     @Override
782     protected String getServiceName() {
783         return SERVICE_NAME;
784     }
785
786     /* (non-Javadoc)
787      * @see org.collectionspace.services.client.test.BaseServiceTest#getServicePathComponent()
788      */
789     @Override
790     public String getServicePathComponent() {
791         return SERVICE_PATH_COMPONENT;
792     }
793
794     /**
795      * Creates the movement instance.
796      *
797      * @param identifier the identifier
798      * @return the multipart output
799      */
800     private PoxPayloadOut createMovementInstance(String identifier) {
801         return createInstance("movementReferenceNumber-" + identifier);
802     }
803
804     /**
805      * Creates an instance of a Movement record for testing.
806      *
807      * @param movementReferenceNumber A movement reference number.
808      * @return Multipart output suitable for use as a payload
809      *     in a create or update request.
810      */
811     @Override
812     public PoxPayloadOut createInstance(String movementReferenceNumber) {
813         MovementsCommon movementCommon = new MovementsCommon();
814         // FIXME: Values of currentLocation, normalLocation,
815         // and movementContact should be refNames.
816         movementCommon.setCurrentLocation("currentLocation value");
817         movementCommon.setCurrentLocationFitness("currentLocationFitness value");
818         movementCommon.setCurrentLocationNote("currentLocationNote value");
819         movementCommon.setLocationDate(TIMESTAMP_UTC);
820         movementCommon.setNormalLocation("normalLocation value");
821         movementCommon.setMovementContact("movementContact value");
822         MovementMethodsList movementMethodsList = new MovementMethodsList();
823         List<String> methods = movementMethodsList.getMovementMethod();
824         // @TODO Use properly formatted refNames for representative movement
825         // methods in this example record. The values below are placeholders.
826         String identifier = createIdentifier();
827         methods.add("First Movement Method-" + identifier);
828         methods.add("Second Movement Method-" + identifier);
829         movementCommon.setMovementMethods(movementMethodsList);
830         movementCommon.setMovementNote(getUTF8DataFragment());
831         movementCommon.setMovementReferenceNumber(movementReferenceNumber);
832         movementCommon.setPlannedRemovalDate(TIMESTAMP_UTC);
833         movementCommon.setRemovalDate(""); // Test empty date value
834         movementCommon.setReasonForMove("reasonForMove value");
835
836         PoxPayloadOut multipart = new PoxPayloadOut(this.getServicePathComponent());
837         PayloadOutputPart commonPart =
838             multipart.addPart(movementCommon, MediaType.APPLICATION_XML_TYPE);
839         commonPart.setLabel(new MovementClient().getCommonPartName());
840
841         if(logger.isDebugEnabled()){
842             logger.debug("to be created, movement common");
843             logger.debug(objectAsXmlString(movementCommon, MovementsCommon.class));
844         }
845
846         return multipart;
847     }
848
849     // FIXME Should be moved to a common class, as these are general utilities.
850     // FIXME Should be refactored to become a convenience variant of a
851     // general method to return a current datestamp or timestamp in any
852     // provided time zone.
853
854    /**
855     * Returns an ISO 8601 formatted timestamp of the
856     * current time instance in the UTC time zone.
857     */
858     public String datestampUTC() {
859         final String ISO_8601_DATE_FORMAT_PATTERN = "yyyy-MM-dd";
860         final DateFormat ISO_8601_DATE_FORMAT =
861             new SimpleDateFormat(ISO_8601_DATE_FORMAT_PATTERN);
862
863         final String UTC_TIMEZONE_IDENTIFIER = "UTC";
864         final TimeZone UTC_TIMEZONE = TimeZone.getTimeZone(UTC_TIMEZONE_IDENTIFIER);
865
866         Date timestamp = new Date();
867         return formatDate(timestamp, UTC_TIMEZONE, ISO_8601_DATE_FORMAT);
868     }
869
870    /**
871     * Returns an ISO 8601 formatted timestamp of the
872     * current time instance in the UTC time zone.
873     */
874     public String timestampUTC() {
875         final String ISO_8601_FORMAT_PATTERN = "yyyy-MM-dd'T'HH:mm:ss'Z'";
876         final DateFormat ISO_8601_FORMAT =
877             new SimpleDateFormat(ISO_8601_FORMAT_PATTERN);
878
879         final String UTC_TIMEZONE_IDENTIFIER = "UTC";
880         final TimeZone UTC_TIMEZONE = TimeZone.getTimeZone(UTC_TIMEZONE_IDENTIFIER);
881
882         Date timestamp = new Date();
883         return formatDate(timestamp, UTC_TIMEZONE, ISO_8601_FORMAT);
884     }
885
886    /**
887     * Formats a provided date using a provided date formatter,
888     * in the default system time zone.
889     *
890     * @param date  A date to format.
891     * @param df    A date formatter to apply.
892     * @return      A formatted date string.
893     */
894     public String formatDate(Date date, DateFormat df) {
895         return formatDate(date, TimeZone.getDefault(), df);
896     }
897
898     // FIXME Add error handling.
899
900    /**
901     * Formats a provided date using a provided date formatter,
902     * in a provided time zone.
903     *
904     * @param date  A date to format.
905     * @param tz    The time zone qualifier for the date to format.
906     * @param df    A date formatter to apply.
907     *
908     * @return      A formatted date string.
909     */
910     public String formatDate(Date date, TimeZone tz, DateFormat df) {
911         df.setTimeZone(tz);
912         return df.format(date);
913     }
914
915 }