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