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