]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
90c1f90335bf59c5b6bd3fac018704c910815357
[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 (c)) 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.ArrayList;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29 import javax.ws.rs.core.MediaType;
30 import javax.ws.rs.core.Response;
31
32 import org.collectionspace.services.VocabularyItemJAXBSchema;
33 import org.collectionspace.services.client.VocabularyClient;
34 import org.collectionspace.services.client.VocabularyClientUtils;
35 import org.collectionspace.services.vocabulary.VocabulariesCommon;
36 import org.collectionspace.services.vocabulary.VocabulariesCommonList;
37 import org.collectionspace.services.vocabulary.VocabularyitemsCommon;
38 import org.collectionspace.services.vocabulary.VocabularyitemsCommonList;
39
40 import org.jboss.resteasy.client.ClientResponse;
41 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
42 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
43 import org.jboss.resteasy.plugins.providers.multipart.OutputPart;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46 import org.testng.Assert;
47 import org.testng.annotations.AfterClass;
48 import org.testng.annotations.Test;
49
50 /**
51  * VocabularyServiceTest, carries out tests against a
52  * deployed and running Vocabulary Service.
53  *
54  * $LastChangedRevision: 753 $
55  * $LastChangedDate: 2009-09-23 11:03:36 -0700 (Wed, 23 Sep 2009) $
56  */
57 public class VocabularyServiceTest extends AbstractServiceTestImpl {
58
59     private final Logger logger =
60         LoggerFactory.getLogger(VocabularyServiceTest.class);
61
62     // Instance variables specific to this test.
63     private VocabularyClient client = new VocabularyClient();
64     final String SERVICE_PATH_COMPONENT = "vocabularies";
65     final String ITEM_SERVICE_PATH_COMPONENT = "items";
66     private String knownResourceId = null;
67     private String knownResourceRefName = null;
68     private String knownItemResourceId = null;
69     private int nItemsToCreateInList = 3;
70     private List<String> allResourceIdsCreated = new ArrayList<String>();
71     private Map<String, String> allResourceItemIdsCreated =
72         new HashMap<String, String>();
73     
74     protected void setKnownResource( String id, String refName ) {
75         knownResourceId = id;
76         knownResourceRefName = refName;
77     }
78
79     // ---------------------------------------------------------------
80     // CRUD tests : CREATE tests
81     // ---------------------------------------------------------------
82     // Success outcomes
83     @Override
84     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class)
85     public void create(String testName) throws Exception {
86
87         // Perform setup, such as initializing the type of service request
88         // (e.g. CREATE, DELETE), its valid and expected status codes, and
89         // its associated HTTP method name (e.g. POST, DELETE).
90         setupCreate(testName);
91
92         // Submit the request to the service and store the response.
93         String identifier = createIdentifier();
94         String displayName = "displayName-" + identifier;
95         String refName = VocabularyClientUtils.createVocabularyRefName(displayName, false);
96         MultipartOutput multipart = VocabularyClientUtils.createEnumerationInstance(
97                                         displayName, refName, client.getCommonPartName());
98         ClientResponse<Response> res = client.create(multipart);
99         int statusCode = res.getStatus();
100
101         // Check the status code of the response: does it match
102         // the expected response(s)?
103         //
104         // Specifically:
105         // Does it fall within the set of valid status codes?
106         // Does it exactly match the expected status code?
107         if(logger.isDebugEnabled()){
108             logger.debug(testName + ": status = " + statusCode);
109         }
110         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
111                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
112         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
113
114         // Store the ID returned from the first resource created
115         // for additional tests below.
116         if (knownResourceId == null){
117                 setKnownResource(extractId(res), refName);
118             if (logger.isDebugEnabled()) {
119                 logger.debug(testName + ": knownResourceId=" + knownResourceId);
120             }
121         }
122         // Store the IDs from every resource created by tests,
123         // so they can be deleted after tests have been run.
124         allResourceIdsCreated.add(extractId(res));
125
126     }
127
128     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
129         dependsOnMethods = {"create"})
130     public void createItem(String testName) {
131         setupCreate(testName);
132
133         HashMap<String, String> itemInfo = new HashMap<String, String>();
134         itemInfo.put(VocabularyItemJAXBSchema.DISPLAY_NAME, createIdentifier());
135         knownItemResourceId = VocabularyClientUtils.createItemInVocabulary(knownResourceId, 
136                                 knownResourceRefName, itemInfo, client);
137         if(logger.isDebugEnabled()){
138             logger.debug(testName + ": knownItemResourceId=" + knownItemResourceId);
139         }
140     }
141
142     @Override
143     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
144             dependsOnMethods = {"create", "createItem"})
145     public void createList(String testName) throws Exception {
146         for (int i = 0; i < 3; i++) {
147                 // Force create to reset the known resource info
148                 setKnownResource(null, null);
149             create(testName);
150             // Add nItemsToCreateInList items to each vocab
151             for (int j = 0; j < nItemsToCreateInList; j++) {
152                 createItem(testName);
153             }
154         }
155     }
156
157     // Failure outcomes
158     // Placeholders until the three tests below can be uncommented.
159     // See Issue CSPACE-401.
160     @Override
161     public void createWithEmptyEntityBody(String testName) throws Exception {
162     }
163
164     @Override
165     public void createWithMalformedXml(String testName) throws Exception {
166     }
167
168     @Override
169     public void createWithWrongXmlSchema(String testName) throws Exception {
170     }
171
172     /*
173     @Override
174     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
175         dependsOnMethods = {"create", "testSubmitRequest"})
176     public void createWithEmptyEntityBody(String testName) throws Exception {
177
178     // Perform setup.
179     setupCreateWithEmptyEntityBody(testName);
180
181     // Submit the request to the service and store the response.
182     String method = REQUEST_TYPE.httpMethodName();
183     String url = getServiceRootURL();
184     String mediaType = MediaType.APPLICATION_XML;
185     final String entity = "";
186     int statusCode = submitRequest(method, url, mediaType, entity);
187
188     // Check the status code of the response: does it match
189     // the expected response(s)?
190     if(logger.isDebugEnabled()) {
191         logger.debug(testName + ": url=" + url +
192             " status=" + statusCode);
193      }
194     Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
195     invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
196     Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
197     }
198
199     @Override
200     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
201         dependsOnMethods = {"create", "testSubmitRequest"})
202     public void createWithMalformedXml(String testName) throws Exception {
203
204     // Perform setup.
205     setupCreateWithMalformedXml(testName);
206
207     // Submit the request to the service and store the response.
208     String method = REQUEST_TYPE.httpMethodName();
209     String url = getServiceRootURL();
210     String mediaType = MediaType.APPLICATION_XML;
211     final String entity = MALFORMED_XML_DATA; // Constant from base class.
212     int statusCode = submitRequest(method, url, mediaType, entity);
213
214     // Check the status code of the response: does it match
215     // the expected response(s)?
216     if(logger.isDebugEnabled()){
217         logger.debug(testName + ": url=" + url +
218             " status=" + statusCode);
219      }
220     Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
221     invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
222     Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
223     }
224
225     @Override
226     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
227         dependsOnMethods = {"create", "testSubmitRequest"})
228     public void createWithWrongXmlSchema(String testName) throws Exception {
229
230     // Perform setup.
231     setupCreateWithWrongXmlSchema(testName);
232
233     // Submit the request to the service and store the response.
234     String method = REQUEST_TYPE.httpMethodName();
235     String url = getServiceRootURL();
236     String mediaType = MediaType.APPLICATION_XML;
237     final String entity = WRONG_XML_SCHEMA_DATA;
238     int statusCode = submitRequest(method, url, mediaType, entity);
239
240     // Check the status code of the response: does it match
241     // the expected response(s)?
242     if(logger.isDebugEnabled()){
243         logger.debug(testName + ": url=" + url +
244             " status=" + statusCode);
245      }
246     Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
247     invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
248     Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
249     }
250      */
251
252     // ---------------------------------------------------------------
253     // CRUD tests : READ tests
254     // ---------------------------------------------------------------
255     // Success outcomes
256     @Override
257     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
258         dependsOnMethods = {"create"})
259     public void read(String testName) throws Exception {
260
261         // Perform setup.
262         setupRead();
263
264         // Submit the request to the service and store the response.
265         ClientResponse<MultipartInput> res = client.read(knownResourceId);
266         int statusCode = res.getStatus();
267
268         // Check the status code of the response: does it match
269         // the expected response(s)?
270         if(logger.isDebugEnabled()){
271             logger.debug(testName + ": status = " + statusCode);
272         }
273         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
274                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
275         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
276         //FIXME: remove the following try catch once Aron fixes signatures
277         try {
278             MultipartInput input = (MultipartInput) res.getEntity();
279             VocabulariesCommon vocabulary = (VocabulariesCommon) extractPart(input,
280                     client.getCommonPartName(), VocabulariesCommon.class);
281             Assert.assertNotNull(vocabulary);
282         } catch (Exception e) {
283             throw new RuntimeException(e);
284         }
285     }
286
287     /*
288     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
289             dependsOnMethods = {"read"})
290         public void readByName(String testName) throws Exception {
291
292             // Perform setup.
293             setupRead();
294
295             // Submit the request to the service and store the response.
296             ClientResponse<MultipartInput> res = client.read(knownResourceId);
297             int statusCode = res.getStatus();
298
299             // Check the status code of the response: does it match
300             // the expected response(s)?
301             if(logger.isDebugEnabled()){
302                 logger.debug(testName + ": status = " + statusCode);
303             }
304             Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
305                     invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
306             Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
307             //FIXME: remove the following try catch once Aron fixes signatures
308             try {
309                 MultipartInput input = (MultipartInput) res.getEntity();
310                 VocabulariesCommon vocabulary = (VocabulariesCommon) extractPart(input,
311                         client.getCommonPartName(), VocabulariesCommon.class);
312                 Assert.assertNotNull(vocabulary);
313             } catch (Exception e) {
314                 throw new RuntimeException(e);
315             }
316         }
317     */
318
319     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
320         dependsOnMethods = {"createItem", "read"})
321     public void readItem(String testName) throws Exception {
322
323         // Perform setup.
324         setupRead(testName);
325
326         // Submit the request to the service and store the response.
327         ClientResponse<MultipartInput> res = client.readItem(knownResourceId, knownItemResourceId);
328         int statusCode = res.getStatus();
329
330         // Check the status code of the response: does it match
331         // the expected response(s)?
332         if(logger.isDebugEnabled()){
333             logger.debug(testName + ": status = " + statusCode);
334         }
335         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
336                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
337         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
338
339         // Check whether we've received a vocabulary item.
340         MultipartInput input = (MultipartInput) res.getEntity();
341         VocabularyitemsCommon vocabularyItem = (VocabularyitemsCommon) extractPart(input,
342                 client.getItemCommonPartName(), VocabularyitemsCommon.class);
343         Assert.assertNotNull(vocabularyItem);
344
345     }
346
347     // Failure outcomes
348     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
349             dependsOnMethods = {"updateItem"})
350     public void verifyIllegalItemDisplayName(String testName) throws Exception {
351
352         // Perform setup.
353         setupUpdateWithWrongXmlSchema(testName);
354
355         // Submit the request to the service and store the response.
356         ClientResponse<MultipartInput> res = client.readItem(knownResourceId, knownItemResourceId);
357         int statusCode = res.getStatus();
358
359         // Check the status code of the response: does it match
360         // the expected response(s)?
361         if(logger.isDebugEnabled()){
362             logger.debug(testName + ": status = " + statusCode);
363         }
364         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
365                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
366         Assert.assertEquals(statusCode, Response.Status.OK.getStatusCode());
367
368         // Check whether Person has expected displayName.
369         MultipartInput input = (MultipartInput) res.getEntity();
370         VocabularyitemsCommon vitem = (VocabularyitemsCommon) extractPart(input,
371                 client.getItemCommonPartName(), VocabularyitemsCommon.class);
372         Assert.assertNotNull(vitem);
373         // Try to Update with null displayName
374         vitem.setDisplayName(null);
375
376         // Submit the updated resource to the service and store the response.
377         MultipartOutput output = new MultipartOutput();
378         OutputPart commonPart = output.addPart(vitem, MediaType.APPLICATION_XML_TYPE);
379         commonPart.getHeaders().add("label", client.getItemCommonPartName());
380         res = client.updateItem(knownResourceId, knownItemResourceId, output);
381         statusCode = res.getStatus();
382
383         // Check the status code of the response: does it match the expected response(s)?
384         if(logger.isDebugEnabled()){
385             logger.debug("updateItem: status = " + statusCode);
386         }
387         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
388                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
389         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE, 
390                         "Expecting invalid message because of null displayName.");
391
392         // Now try to Update with 1-char displayName (too short)
393         vitem.setDisplayName("a");
394
395         // Submit the updated resource to the service and store the response.
396         output = new MultipartOutput();
397         commonPart = output.addPart(vitem, MediaType.APPLICATION_XML_TYPE);
398         commonPart.getHeaders().add("label", client.getItemCommonPartName());
399         res = client.updateItem(knownResourceId, knownItemResourceId, output);
400         statusCode = res.getStatus();
401
402         // Check the status code of the response: does it match the expected response(s)?
403         if(logger.isDebugEnabled()){
404             logger.debug("updateItem: status = " + statusCode);
405         }
406         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
407                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
408         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE, 
409                 "Expecting invalid message because of 1-char displayName.");
410     }
411
412     @Override
413     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
414         dependsOnMethods = {"read"})
415     public void readNonExistent(String testName) {
416
417         // Perform setup.
418         setupReadNonExistent(testName);
419
420         // Submit the request to the service and store the response.
421         ClientResponse<MultipartInput> res = client.read(NON_EXISTENT_ID);
422         int statusCode = res.getStatus();
423
424         // Check the status code of the response: does it match
425         // the expected response(s)?
426         if(logger.isDebugEnabled()){
427             logger.debug(testName + ": status = " + statusCode);
428         }
429         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
430                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
431         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
432     }
433
434     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
435         dependsOnMethods = {"readItem", "readNonExistent"})
436     public void readItemNonExistent(String testName) {
437
438         // Perform setup.
439         setupReadNonExistent(testName);
440
441         // Submit the request to the service and store the response.
442         ClientResponse<MultipartInput> res = client.readItem(knownResourceId, NON_EXISTENT_ID);
443         int statusCode = res.getStatus();
444
445         // Check the status code of the response: does it match
446         // the expected response(s)?
447         if(logger.isDebugEnabled()){
448             logger.debug(testName + ": status = " + statusCode);
449         }
450         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
451                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
452         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
453     }
454     // ---------------------------------------------------------------
455     // CRUD tests : READ_LIST tests
456     // ---------------------------------------------------------------
457     // Success outcomes
458
459     @Override
460     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
461         dependsOnMethods = {"createList", "read"})
462     public void readList(String testName) throws Exception {
463
464         // Perform setup.
465         setupReadList(testName);
466
467         // Submit the request to the service and store the response.
468         ClientResponse<VocabulariesCommonList> res = client.readList();
469         VocabulariesCommonList list = res.getEntity();
470         int statusCode = res.getStatus();
471
472         // Check the status code of the response: does it match
473         // the expected response(s)?
474         if(logger.isDebugEnabled()){
475             logger.debug(testName + ": status = " + statusCode);
476         }
477         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
478                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
479         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
480
481         // Optionally output additional data about list members for debugging.
482         boolean iterateThroughList = false;
483         if (iterateThroughList && logger.isDebugEnabled()) {
484             List<VocabulariesCommonList.VocabularyListItem> items =
485                     list.getVocabularyListItem();
486             int i = 0;
487             for (VocabulariesCommonList.VocabularyListItem item : items) {
488                 String csid = item.getCsid();
489                 logger.debug(testName + ": list-item[" + i + "] csid=" +
490                         csid);
491                 logger.debug(testName + ": list-item[" + i + "] displayName=" +
492                         item.getDisplayName());
493                 logger.debug(testName + ": list-item[" + i + "] URI=" +
494                         item.getUri());
495                 readItemList(csid);
496                 i++;
497             }
498         }
499     }
500
501     @Test(dependsOnMethods = {"createList", "readItem"})
502     public void readItemList() {
503         readItemList(knownResourceId);
504     }
505
506     private void readItemList(String vcsid) {
507
508         final String testName = "readItemList";
509
510         // Perform setup.
511         setupReadList(testName);
512
513         // Submit the request to the service and store the response.
514         ClientResponse<VocabularyitemsCommonList> res =
515                 client.readItemList(vcsid);
516         VocabularyitemsCommonList list = res.getEntity();
517         int statusCode = res.getStatus();
518
519         // Check the status code of the response: does it match
520         // the expected response(s)?
521         if(logger.isDebugEnabled()){
522             logger.debug("  " + testName + ": status = " + statusCode);
523         }
524         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
525                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
526         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
527
528         List<VocabularyitemsCommonList.VocabularyitemListItem> items =
529             list.getVocabularyitemListItem();
530         int nItemsReturned = items.size();
531         if(logger.isDebugEnabled()){
532             logger.debug("  " + testName + ": Expected "
533                         + nItemsToCreateInList+" items; got: "+nItemsReturned);
534         }
535         Assert.assertEquals( nItemsReturned, nItemsToCreateInList);
536
537         // Optionally output additional data about list members for debugging.
538         boolean iterateThroughList = true;
539         if (iterateThroughList && logger.isDebugEnabled()) {
540             logger.debug("  " + testName + ": checking items");
541             int i = 0;
542             for (VocabularyitemsCommonList.VocabularyitemListItem item : items) {
543                 logger.debug("  " + testName + ": list-item[" + i + "] csid=" +
544                         item.getCsid());
545                 logger.debug("  " + testName + ": list-item[" + i + "] displayName=" +
546                         item.getDisplayName());
547                 logger.debug("  " + testName + ": list-item[" + i + "] URI=" +
548                         item.getUri());
549                 i++;
550             }
551         }
552     }
553
554     // Failure outcomes
555     // None at present.
556     // ---------------------------------------------------------------
557     // CRUD tests : UPDATE tests
558     // ---------------------------------------------------------------
559     // Success outcomes
560     @Override
561     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
562         dependsOnMethods = {"read"})
563     public void update(String testName) throws Exception {
564
565         // Perform setup.
566         setupUpdate(testName);
567
568         // Retrieve the contents of a resource to update.
569         ClientResponse<MultipartInput> res =
570                 client.read(knownResourceId);
571         if(logger.isDebugEnabled()){
572             logger.debug(testName + ": read status = " + res.getStatus());
573         }
574         Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE);
575
576         if(logger.isDebugEnabled()){
577             logger.debug("got Vocabulary to update with ID: " + knownResourceId);
578         }
579         MultipartInput input = (MultipartInput) res.getEntity();
580         VocabulariesCommon vocabulary = (VocabulariesCommon) extractPart(input,
581                 client.getCommonPartName(), VocabulariesCommon.class);
582         Assert.assertNotNull(vocabulary);
583
584         // Update the contents of this resource.
585         vocabulary.setDisplayName("updated-" + vocabulary.getDisplayName());
586         vocabulary.setVocabType("updated-" + vocabulary.getVocabType());
587         if(logger.isDebugEnabled()){
588             logger.debug("to be updated Vocabulary");
589             logger.debug(objectAsXmlString(vocabulary, VocabulariesCommon.class));
590         }
591
592         // Submit the updated resource to the service and store the response.
593         MultipartOutput output = new MultipartOutput();
594         OutputPart commonPart = output.addPart(vocabulary, MediaType.APPLICATION_XML_TYPE);
595         commonPart.getHeaders().add("label", client.getCommonPartName());
596         res = client.update(knownResourceId, output);
597         int statusCode = res.getStatus();
598
599         // Check the status code of the response: does it match the expected response(s)?
600         if(logger.isDebugEnabled()){
601             logger.debug("update: status = " + statusCode);
602         }
603         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
604                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
605         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
606
607         // Retrieve the updated resource and verify that its contents exist.
608         input = (MultipartInput) res.getEntity();
609         VocabulariesCommon updatedVocabulary =
610                 (VocabulariesCommon) extractPart(input,
611                         client.getCommonPartName(), VocabulariesCommon.class);
612         Assert.assertNotNull(updatedVocabulary);
613
614         // Verify that the updated resource received the correct data.
615         Assert.assertEquals(updatedVocabulary.getDisplayName(),
616                 vocabulary.getDisplayName(),
617                 "Data in updated object did not match submitted data.");
618     }
619
620     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
621         dependsOnMethods = {"readItem", "update"})
622     public void updateItem(String testName) throws Exception {
623
624         // Perform setup.
625         setupUpdate(testName);
626
627         ClientResponse<MultipartInput> res =
628                 client.readItem(knownResourceId, knownItemResourceId);
629         if(logger.isDebugEnabled()){
630             logger.debug(testName + ": read status = " + res.getStatus());
631         }
632         Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE);
633
634         if(logger.isDebugEnabled()){
635             logger.debug("got VocabularyItem to update with ID: " +
636                 knownItemResourceId +
637                 " in Vocab: " + knownResourceId );
638         }
639         MultipartInput input = (MultipartInput) res.getEntity();
640         VocabularyitemsCommon vocabularyItem = (VocabularyitemsCommon) extractPart(input,
641                 client.getItemCommonPartName(), VocabularyitemsCommon.class);
642         Assert.assertNotNull(vocabularyItem);
643
644         // Update the contents of this resource.
645         vocabularyItem.setDisplayName("updated-" + vocabularyItem.getDisplayName());
646         if(logger.isDebugEnabled()){
647             logger.debug("to be updated VocabularyItem");
648             logger.debug(objectAsXmlString(vocabularyItem,
649                 VocabularyitemsCommon.class));
650         }
651
652         // Submit the updated resource to the service and store the response.
653         MultipartOutput output = new MultipartOutput();
654         OutputPart commonPart = output.addPart(vocabularyItem, MediaType.APPLICATION_XML_TYPE);
655         commonPart.getHeaders().add("label", client.getItemCommonPartName());
656         res = client.updateItem(knownResourceId, knownItemResourceId, output);
657         int statusCode = res.getStatus();
658
659         // Check the status code of the response: does it match the expected response(s)?
660         if(logger.isDebugEnabled()){
661             logger.debug("updateItem: status = " + statusCode);
662         }
663         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
664                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
665         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
666
667         // Retrieve the updated resource and verify that its contents exist.
668         input = (MultipartInput) res.getEntity();
669         VocabularyitemsCommon updatedVocabularyItem =
670                 (VocabularyitemsCommon) extractPart(input,
671                         client.getItemCommonPartName(), VocabularyitemsCommon.class);
672         Assert.assertNotNull(updatedVocabularyItem);
673
674         // Verify that the updated resource received the correct data.
675         Assert.assertEquals(updatedVocabularyItem.getDisplayName(),
676                 vocabularyItem.getDisplayName(),
677                 "Data in updated VocabularyItem did not match submitted data.");
678     }
679
680     // Failure outcomes
681     // Placeholders until the three tests below can be uncommented.
682     // See Issue CSPACE-401.
683     @Override
684     public void updateWithEmptyEntityBody(String testName) throws Exception {
685     }
686
687     @Override
688     public void updateWithMalformedXml(String testName) throws Exception {
689     }
690
691     @Override
692     public void updateWithWrongXmlSchema(String testName) throws Exception {
693     }
694
695     /*
696     @Override
697     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
698         dependsOnMethods = {"create", "update", "testSubmitRequest"})
699     public void updateWithEmptyEntityBody(String testName) throws Exception {
700
701     // Perform setup.
702     setupUpdateWithEmptyEntityBody(testName);
703
704     // Submit the request to the service and store the response.
705     String method = REQUEST_TYPE.httpMethodName();
706     String url = getResourceURL(knownResourceId);
707     String mediaType = MediaType.APPLICATION_XML;
708     final String entity = "";
709     int statusCode = submitRequest(method, url, mediaType, entity);
710
711     // Check the status code of the response: does it match
712     // the expected response(s)?
713     if(logger.isDebugEnabled()){
714         logger.debug(testName + ": url=" + url +
715             " status=" + statusCode);
716      }
717     Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
718     invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
719     Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
720     }
721
722     @Override
723     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
724         dependsOnMethods = {"create", "update", "testSubmitRequest"})
725     public void updateWithMalformedXml(String testName) throws Exception {
726
727     // Perform setup.
728     setupUpdateWithMalformedXml(testName);
729
730     // Submit the request to the service and store the response.
731     String method = REQUEST_TYPE.httpMethodName();
732     String url = getResourceURL(knownResourceId);
733     String mediaType = MediaType.APPLICATION_XML;
734     final String entity = MALFORMED_XML_DATA;
735     int statusCode = submitRequest(method, url, mediaType, entity);
736
737     // Check the status code of the response: does it match
738     // the expected response(s)?
739     if(logger.isDebugEnabled()){
740         logger.debug(testName + ": url=" + url +
741            " status=" + statusCode);
742      }
743     Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
744     invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
745     Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
746     }
747
748     @Override
749     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
750         dependsOnMethods = {"create", "update", "testSubmitRequest"})
751     public void updateWithWrongXmlSchema(String testName) throws Exception {
752
753     // Perform setup.
754     setupUpdateWithWrongXmlSchema(testName);
755
756     // Submit the request to the service and store the response.
757     String method = REQUEST_TYPE.httpMethodName();
758     String url = getResourceURL(knownResourceId);
759     String mediaType = MediaType.APPLICATION_XML;
760     final String entity = WRONG_XML_SCHEMA_DATA;
761     int statusCode = submitRequest(method, url, mediaType, entity);
762
763     // Check the status code of the response: does it match
764     // the expected response(s)?
765     if(logger.isDebugEnabled()){
766         logger.debug("updateWithWrongXmlSchema: url=" + url +
767             " status=" + statusCode);
768      }
769     Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
770     invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
771     Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
772     }
773      */
774
775
776     @Override
777     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
778         dependsOnMethods = {"update", "testSubmitRequest"})
779     public void updateNonExistent(String testName) throws Exception {
780
781         // Perform setup.
782         setupUpdateNonExistent(testName);
783
784         // Submit the request to the service and store the response.
785         // Note: The ID used in this 'create' call may be arbitrary.
786         // The only relevant ID may be the one used in update(), below.
787
788         // The only relevant ID may be the one used in update(), below.
789         String displayName = "displayName-" + NON_EXISTENT_ID;
790         String refName = VocabularyClientUtils.createVocabularyRefName(displayName, false);
791         MultipartOutput multipart = VocabularyClientUtils.createEnumerationInstance(
792                                 displayName, refName, client.getCommonPartName());
793         ClientResponse<MultipartInput> res =
794                 client.update(NON_EXISTENT_ID, multipart);
795         int statusCode = res.getStatus();
796
797         // Check the status code of the response: does it match
798         // the expected response(s)?
799         if(logger.isDebugEnabled()){
800             logger.debug(testName + ": status = " + statusCode);
801         }
802         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
803                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
804         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
805     }
806
807     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
808         dependsOnMethods = {"updateItem", "testItemSubmitRequest"})
809     public void updateNonExistentItem(String testName) throws Exception {
810
811         // Perform setup.
812         setupUpdateNonExistent(testName);
813
814         // Submit the request to the service and store the response.
815         // Note: The ID used in this 'create' call may be arbitrary.
816         // The only relevant ID may be the one used in update(), below.
817
818         // The only relevant ID may be the one used in update(), below.
819         HashMap<String, String> itemInfo = new HashMap<String, String>();
820         itemInfo.put(VocabularyItemJAXBSchema.DISPLAY_NAME, "nonex");
821         MultipartOutput multipart = 
822                 VocabularyClientUtils.createVocabularyItemInstance(knownResourceId, 
823                         VocabularyClientUtils.createVocabularyItemRefName(NON_EXISTENT_ID, NON_EXISTENT_ID, true),
824                         itemInfo, client.getItemCommonPartName());
825         ClientResponse<MultipartInput> res =
826                 client.updateItem(knownResourceId, NON_EXISTENT_ID, multipart);
827         int statusCode = res.getStatus();
828
829         // Check the status code of the response: does it match
830         // the expected response(s)?
831         if(logger.isDebugEnabled()){
832             logger.debug(testName + ": status = " + statusCode);
833         }
834         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
835                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
836         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
837     }
838
839     // ---------------------------------------------------------------
840     // CRUD tests : DELETE tests
841     // ---------------------------------------------------------------
842     // Success outcomes
843     @Override
844     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
845         dependsOnMethods = {"create", "readList", "testSubmitRequest", "update"})
846     public void delete(String testName) throws Exception {
847
848         // Perform setup.
849         setupDelete(testName);
850
851         // Submit the request to the service and store the response.
852         ClientResponse<Response> res = client.delete(knownResourceId);
853         int statusCode = res.getStatus();
854
855         // Check the status code of the response: does it match
856         // the expected response(s)?
857         if(logger.isDebugEnabled()){
858             logger.debug(testName + ": status = " + statusCode);
859         }
860         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
861                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
862         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
863     }
864
865    @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
866         dependsOnMethods = {"createItem", "readItemList", "testItemSubmitRequest",
867             "updateItem", "verifyIllegalItemDisplayName"})
868     public void deleteItem(String testName) throws Exception {
869
870         // Perform setup.
871         setupDelete(testName);
872
873         // Submit the request to the service and store the response.
874         ClientResponse<Response> res = client.deleteItem(knownResourceId, knownItemResourceId);
875         int statusCode = res.getStatus();
876
877         // Check the status code of the response: does it match
878         // the expected response(s)?
879         if(logger.isDebugEnabled()){
880             logger.debug("delete: status = " + statusCode);
881         }
882         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
883                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
884         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
885     }
886
887     // Failure outcomes
888     @Override
889     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
890         dependsOnMethods = {"delete"})
891     public void deleteNonExistent(String testName) throws Exception {
892
893         // Perform setup.
894         setupDeleteNonExistent(testName);
895
896         // Submit the request to the service and store the response.
897         ClientResponse<Response> res = client.delete(NON_EXISTENT_ID);
898         int statusCode = res.getStatus();
899
900         // Check the status code of the response: does it match
901         // the expected response(s)?
902         if(logger.isDebugEnabled()){
903             logger.debug(testName + ": status = " + statusCode);
904         }
905         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
906                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
907         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
908     }
909
910     @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
911         dependsOnMethods = {"deleteItem"})
912     public void deleteNonExistentItem(String testName) {
913
914         // Perform setup.
915         setupDeleteNonExistent(testName);
916
917         // Submit the request to the service and store the response.
918         ClientResponse<Response> res = client.deleteItem(knownResourceId, NON_EXISTENT_ID);
919         int statusCode = res.getStatus();
920
921         // Check the status code of the response: does it match
922         // the expected response(s)?
923         if(logger.isDebugEnabled()){
924             logger.debug(testName + ": status = " + statusCode);
925         }
926         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
927                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
928         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
929     }
930
931     // ---------------------------------------------------------------
932     // Utility tests : tests of code used in tests above
933     // ---------------------------------------------------------------
934     /**
935      * Tests the code for manually submitting data that is used by several
936      * of the methods above.
937      */
938     @Test(dependsOnMethods = {"create", "read"})
939     public void testSubmitRequest() {
940
941         // Expected status code: 200 OK
942         final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
943
944         // Submit the request to the service and store the response.
945         String method = ServiceRequestType.READ.httpMethodName();
946         String url = getResourceURL(knownResourceId);
947         int statusCode = submitRequest(method, url);
948
949         // Check the status code of the response: does it match
950         // the expected response(s)?
951         if(logger.isDebugEnabled()){
952             logger.debug("testSubmitRequest: url=" + url +
953                 " status=" + statusCode);
954         }
955         Assert.assertEquals(statusCode, EXPECTED_STATUS);
956
957     }
958
959     @Test(dependsOnMethods = {"createItem", "readItem", "testSubmitRequest"})
960     public void testItemSubmitRequest() {
961
962         // Expected status code: 200 OK
963         final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
964
965         // Submit the request to the service and store the response.
966         String method = ServiceRequestType.READ.httpMethodName();
967         String url = getItemResourceURL(knownResourceId, knownItemResourceId);
968         int statusCode = submitRequest(method, url);
969
970         // Check the status code of the response: does it match
971         // the expected response(s)?
972         if(logger.isDebugEnabled()){
973             logger.debug("testItemSubmitRequest: url=" + url +
974                 " status=" + statusCode);
975         }
976         Assert.assertEquals(statusCode, EXPECTED_STATUS);
977
978     }
979
980     // ---------------------------------------------------------------
981     // Cleanup of resources created during testing
982     // ---------------------------------------------------------------
983     
984     /**
985      * Deletes all resources created by tests, after all tests have been run.
986      *
987      * This cleanup method will always be run, even if one or more tests fail.
988      * For this reason, it attempts to remove all resources created
989      * at any point during testing, even if some of those resources
990      * may be expected to be deleted by certain tests.
991      */
992     @AfterClass(alwaysRun=true)
993     public void cleanUp() {
994
995         if (logger.isDebugEnabled()) {
996             logger.debug("Cleaning up temporary resources created for testing ...");
997         }
998         // Clean up vocabulary item resources.
999         String vocabularyResourceId;
1000         String vocabularyItemResourceId;
1001         for (Map.Entry<String, String> entry : allResourceItemIdsCreated.entrySet()) {
1002             vocabularyItemResourceId = entry.getKey();
1003             vocabularyResourceId = entry.getValue();
1004             // Note: Any non-success responses are ignored and not reported.
1005             ClientResponse<Response> res =
1006                 client.deleteItem(vocabularyResourceId, vocabularyItemResourceId);
1007         }
1008         // Clean up vocabulary resources.
1009         for (String resourceId : allResourceIdsCreated) {
1010             // Note: Any non-success responses are ignored and not reported.
1011             ClientResponse<Response> res = client.delete(resourceId);
1012         }
1013
1014     }
1015
1016     // ---------------------------------------------------------------
1017     // Utility methods used by tests above
1018     // ---------------------------------------------------------------
1019     @Override
1020     public String getServicePathComponent() {
1021         return SERVICE_PATH_COMPONENT;
1022     }
1023
1024     public String getItemServicePathComponent() {
1025         return ITEM_SERVICE_PATH_COMPONENT;
1026     }
1027
1028     /**
1029      * Returns the root URL for a service.
1030      *
1031      * This URL consists of a base URL for all services, followed by
1032      * a path component for the owning vocabulary, followed by the 
1033      * path component for the items.
1034      *
1035      * @return The root URL for a service.
1036      */
1037     protected String getItemServiceRootURL(String parentResourceIdentifier) {
1038         return getResourceURL(parentResourceIdentifier) + "/" + getItemServicePathComponent();
1039     }
1040
1041     /**
1042      * Returns the URL of a specific resource managed by a service, and
1043      * designated by an identifier (such as a universally unique ID, or UUID).
1044      *
1045      * @param  resourceIdentifier  An identifier (such as a UUID) for a resource.
1046      *
1047      * @return The URL of a specific resource managed by a service.
1048      */
1049     protected String getItemResourceURL(String parentResourceIdentifier, String resourceIdentifier) {
1050         return getItemServiceRootURL(parentResourceIdentifier) + "/" + resourceIdentifier;
1051     }
1052
1053
1054
1055 }