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:
6 * http://www.collectionspace.org
7 * http://wiki.collectionspace.org
9 * Copyright (c)) 2009 Regents of the University of California
11 * Licensed under the Educational Community License (ECL), Version 2.0.
12 * You may not use this file except in compliance with this License.
14 * You may obtain a copy of the ECL 2.0 License at
15 * https://source.collectionspace.org/collection-space/LICENSE.txt
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.
23 package org.collectionspace.services.client.test;
25 import java.util.ArrayList;
26 import java.util.HashMap;
27 import java.util.List;
29 import javax.ws.rs.core.MediaType;
30 import javax.ws.rs.core.Response;
32 import org.collectionspace.services.VocabularyItemJAXBSchema;
33 import org.collectionspace.services.client.CollectionSpaceClient;
34 import org.collectionspace.services.client.VocabularyClient;
35 import org.collectionspace.services.client.VocabularyClientUtils;
36 import org.collectionspace.services.jaxb.AbstractCommonList;
37 import org.collectionspace.services.vocabulary.VocabulariesCommon;
38 import org.collectionspace.services.vocabulary.VocabulariesCommonList;
39 import org.collectionspace.services.vocabulary.VocabularyitemsCommon;
40 import org.collectionspace.services.vocabulary.VocabularyitemsCommonList;
42 import org.jboss.resteasy.client.ClientResponse;
43 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
44 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
45 import org.jboss.resteasy.plugins.providers.multipart.OutputPart;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48 import org.testng.Assert;
49 import org.testng.annotations.AfterClass;
50 import org.testng.annotations.Test;
53 * VocabularyServiceTest, carries out tests against a
54 * deployed and running Vocabulary Service.
56 * $LastChangedRevision: 753 $
57 * $LastChangedDate: 2009-09-23 11:03:36 -0700 (Wed, 23 Sep 2009) $
59 public class VocabularyServiceTest extends AbstractServiceTestImpl {
61 private final String CLASS_NAME = VocabularyServiceTest.class.getName();
62 private final Logger logger = LoggerFactory.getLogger(CLASS_NAME);
64 // Instance variables specific to this test.
65 final String SERVICE_PATH_COMPONENT = "vocabularies";
66 final String ITEM_SERVICE_PATH_COMPONENT = "items";
67 private String knownResourceId = null;
68 private String knownResourceShortIdentifer = null;
69 private String knownResourceRefName = null;
70 private String knownResourceFullRefName = null;
71 private String knownItemResourceId = null;
72 private int nItemsToCreateInList = 3;
73 private List<String> allResourceIdsCreated = new ArrayList<String>();
74 private Map<String, String> allResourceItemIdsCreated =
75 new HashMap<String, String>();
77 protected void setKnownResource( String id, String shortIdentifer,
78 String refName, String fullRefName ) {
80 knownResourceShortIdentifer = shortIdentifer;
81 knownResourceRefName = refName;
82 knownResourceFullRefName = fullRefName;
86 * @see org.collectionspace.services.client.test.BaseServiceTest#getClientInstance()
89 protected CollectionSpaceClient getClientInstance() {
90 return new VocabularyClient();
94 * @see org.collectionspace.services.client.test.BaseServiceTest#getAbstractCommonList(org.jboss.resteasy.client.ClientResponse)
97 protected AbstractCommonList getAbstractCommonList(
98 ClientResponse<AbstractCommonList> response) {
99 return response.getEntity(VocabulariesCommonList.class);
102 // ---------------------------------------------------------------
103 // CRUD tests : CREATE tests
104 // ---------------------------------------------------------------
107 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class)
108 public void create(String testName) throws Exception {
110 if (logger.isDebugEnabled()) {
111 logger.debug(testBanner(testName, CLASS_NAME));
113 // Perform setup, such as initializing the type of service request
114 // (e.g. CREATE, DELETE), its valid and expected status codes, and
115 // its associated HTTP method name (e.g. POST, DELETE).
118 // Submit the request to the service and store the response.
119 VocabularyClient client = new VocabularyClient();
120 String identifier = createIdentifier();
121 String displayName = "displayName-" + identifier;
122 MultipartOutput multipart = VocabularyClientUtils.createEnumerationInstance(
123 displayName, identifier, client.getCommonPartName());
124 ClientResponse<Response> res = client.create(multipart);
125 int statusCode = res.getStatus();
127 // Check the status code of the response: does it match
128 // the expected response(s)?
131 // Does it fall within the set of valid status codes?
132 // Does it exactly match the expected status code?
133 if(logger.isDebugEnabled()){
134 logger.debug(testName + ": status = " + statusCode);
136 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
137 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
138 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
140 // Store the ID returned from the first resource created
141 // for additional tests below.
142 if (knownResourceId == null){
143 setKnownResource(extractId(res), identifier,
144 VocabularyClientUtils.createVocabularyRefName(identifier, null),
145 VocabularyClientUtils.createVocabularyRefName(identifier, displayName));
146 if (logger.isDebugEnabled()) {
147 logger.debug(testName + ": knownResourceId=" + knownResourceId);
150 // Store the IDs from every resource created by tests,
151 // so they can be deleted after tests have been run.
152 allResourceIdsCreated.add(extractId(res));
156 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
157 dependsOnMethods = {"create"})
158 public void createItem(String testName) {
160 if (logger.isDebugEnabled()) {
161 logger.debug(testBanner(testName, CLASS_NAME));
166 VocabularyClient client = new VocabularyClient();
167 HashMap<String, String> itemInfo = new HashMap<String, String>();
168 String shortId = createIdentifier();
169 itemInfo.put(VocabularyItemJAXBSchema.SHORT_IDENTIFIER, shortId);
170 itemInfo.put(VocabularyItemJAXBSchema.DISPLAY_NAME, "display-"+shortId);
171 String newID = VocabularyClientUtils.createItemInVocabulary(knownResourceId,
172 knownResourceRefName, itemInfo, client);
174 // Store the ID returned from the first item resource created
175 // for additional tests below.
176 if (knownItemResourceId == null){
177 knownItemResourceId = newID;
178 if (logger.isDebugEnabled()) {
179 logger.debug(testName + ": knownItemResourceId=" + knownItemResourceId);
182 // Store the IDs from any item resources created
183 // by tests, along with the IDs of their parents, so these items
184 // can be deleted after all tests have been run.
185 allResourceItemIdsCreated.put(newID, knownResourceId);
189 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
190 dependsOnMethods = {"create", "createItem"})
191 public void createList(String testName) throws Exception {
192 for (int i = 0; i < 3; i++) {
193 // Force create to reset the known resource info
194 setKnownResource(null, null, null, null);
196 // Add nItemsToCreateInList items to each vocab
197 for (int j = 0; j < nItemsToCreateInList; j++) {
198 createItem(testName);
204 // Placeholders until the three tests below can be uncommented.
205 // See Issue CSPACE-401.
207 public void createWithEmptyEntityBody(String testName) throws Exception {
211 public void createWithMalformedXml(String testName) throws Exception {
215 public void createWithWrongXmlSchema(String testName) throws Exception {
218 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
219 dependsOnMethods = {"create"})
220 public void createWithBadShortId(String testName) throws Exception {
222 if (logger.isDebugEnabled()) {
223 logger.debug(testBanner(testName, CLASS_NAME));
225 testSetup(STATUS_BAD_REQUEST, ServiceRequestType.CREATE);
227 // Submit the request to the service and store the response.
228 VocabularyClient client = new VocabularyClient();
229 MultipartOutput multipart = VocabularyClientUtils.createEnumerationInstance(
230 "Vocab with Bad Short Id", "Bad Short Id!", client.getCommonPartName());
231 ClientResponse<Response> res = client.create(multipart);
232 int statusCode = res.getStatus();
234 // Check the status code of the response: does it match
235 // the expected response(s)?
238 // Does it fall within the set of valid status codes?
239 // Does it exactly match the expected status code?
240 if(logger.isDebugEnabled()){
241 logger.debug(testName + ": status = " + statusCode);
243 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
244 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
245 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
248 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
249 dependsOnMethods = {"createItem"})
250 public void createItemWithBadShortId(String testName) throws Exception {
252 if (logger.isDebugEnabled()) {
253 logger.debug(testBanner(testName, CLASS_NAME));
255 setupCreateWithMalformedXml();
257 // Submit the request to the service and store the response.
258 VocabularyClient client = new VocabularyClient();
259 HashMap<String, String> itemInfo = new HashMap<String, String>();
260 itemInfo.put(VocabularyItemJAXBSchema.SHORT_IDENTIFIER, "Bad Item Short Id!");
261 itemInfo.put(VocabularyItemJAXBSchema.DISPLAY_NAME, "Bad Item!");
262 MultipartOutput multipart =
263 VocabularyClientUtils.createVocabularyItemInstance( knownResourceId, knownResourceRefName,
264 itemInfo, client.getItemCommonPartName() );
265 ClientResponse<Response> res = client.createItem(knownResourceId, multipart);
267 int statusCode = res.getStatus();
269 if(!REQUEST_TYPE.isValidStatusCode(statusCode)) {
270 throw new RuntimeException("Could not create Item: \""+itemInfo.get(VocabularyItemJAXBSchema.DISPLAY_NAME)
271 +"\" in personAuthority: \"" + knownResourceRefName
272 +"\" "+ invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
274 if(statusCode != EXPECTED_STATUS_CODE) {
275 throw new RuntimeException("Unexpected Status when creating Item: \""+itemInfo.get(VocabularyItemJAXBSchema.DISPLAY_NAME)
276 +"\" in personAuthority: \"" + knownResourceRefName +"\", Status:"+ statusCode);
282 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
283 dependsOnMethods = {"create", "testSubmitRequest"})
284 public void createWithEmptyEntityBody(String testName) throws Exception {
286 if (logger.isDebugEnabled()) {
287 logger.debug(testBanner(testName, CLASS_NAME));
290 setupCreateWithEmptyEntityBody(testName, CLASS_NAME);
292 // Submit the request to the service and store the response.
293 String method = REQUEST_TYPE.httpMethodName();
294 String url = getServiceRootURL();
295 String mediaType = MediaType.APPLICATION_XML;
296 final String entity = "";
297 int statusCode = submitRequest(method, url, mediaType, entity);
299 // Check the status code of the response: does it match
300 // the expected response(s)?
301 if(logger.isDebugEnabled()) {
302 logger.debug(testName + ": url=" + url +
303 " status=" + statusCode);
305 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
306 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
307 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
311 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
312 dependsOnMethods = {"create", "testSubmitRequest"})
313 public void createWithMalformedXml(String testName) throws Exception {
315 if (logger.isDebugEnabled()) {
316 logger.debug(testBanner(testName, CLASS_NAME));
319 setupCreateWithMalformedXml();
321 // Submit the request to the service and store the response.
322 String method = REQUEST_TYPE.httpMethodName();
323 String url = getServiceRootURL();
324 String mediaType = MediaType.APPLICATION_XML;
325 final String entity = MALFORMED_XML_DATA; // Constant from base class.
326 int statusCode = submitRequest(method, url, mediaType, entity);
328 // Check the status code of the response: does it match
329 // the expected response(s)?
330 if(logger.isDebugEnabled()){
331 logger.debug(testName + ": url=" + url +
332 " status=" + statusCode);
334 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
335 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
336 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
340 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
341 dependsOnMethods = {"create", "testSubmitRequest"})
342 public void createWithWrongXmlSchema(String testName) throws Exception {
344 if (logger.isDebugEnabled()) {
345 logger.debug(testBanner(testName, CLASS_NAME));
348 setupCreateWithWrongXmlSchema();
350 // Submit the request to the service and store the response.
351 String method = REQUEST_TYPE.httpMethodName();
352 String url = getServiceRootURL();
353 String mediaType = MediaType.APPLICATION_XML;
354 final String entity = WRONG_XML_SCHEMA_DATA;
355 int statusCode = submitRequest(method, url, mediaType, entity);
357 // Check the status code of the response: does it match
358 // the expected response(s)?
359 if(logger.isDebugEnabled()){
360 logger.debug(testName + ": url=" + url +
361 " status=" + statusCode);
363 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
364 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
365 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
369 // ---------------------------------------------------------------
370 // CRUD tests : READ tests
371 // ---------------------------------------------------------------
374 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
375 dependsOnMethods = {"create"})
376 public void read(String testName) throws Exception {
378 if (logger.isDebugEnabled()) {
379 logger.debug(testBanner(testName, CLASS_NAME));
384 // Submit the request to the service and store the response.
385 VocabularyClient client = new VocabularyClient();
386 ClientResponse<MultipartInput> res = client.read(knownResourceId);
387 int statusCode = res.getStatus();
389 // Check the status code of the response: does it match
390 // the expected response(s)?
391 if(logger.isDebugEnabled()){
392 logger.debug(testName + ": status = " + statusCode);
394 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
395 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
396 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
397 //FIXME: remove the following try catch once Aron fixes signatures
399 MultipartInput input = (MultipartInput) res.getEntity();
400 VocabulariesCommon vocabulary = (VocabulariesCommon) extractPart(input,
401 client.getCommonPartName(), VocabulariesCommon.class);
402 Assert.assertNotNull(vocabulary);
403 Assert.assertEquals(vocabulary.getRefName(), knownResourceFullRefName);
404 } catch (Exception e) {
405 throw new RuntimeException(e);
412 * @param testName the test name
413 * @throws Exception the exception
415 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
416 dependsOnMethods = {"read"})
417 public void readByName(String testName) throws Exception {
419 if (logger.isDebugEnabled()) {
420 logger.debug(testBanner(testName, CLASS_NAME));
425 // Submit the request to the service and store the response.
426 VocabularyClient client = new VocabularyClient();
427 ClientResponse<MultipartInput> res = client.readByName(knownResourceShortIdentifer);
429 int statusCode = res.getStatus();
431 // Check the status code of the response: does it match
432 // the expected response(s)?
433 if(logger.isDebugEnabled()){
434 logger.debug(testName + ": status = " + statusCode);
436 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
437 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
438 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
439 //FIXME: remove the following try catch once Aron fixes signatures
441 MultipartInput input = (MultipartInput) res.getEntity();
442 VocabulariesCommon vocabulary = (VocabulariesCommon) extractPart(input,
443 client.getCommonPartName(), VocabulariesCommon.class);
444 Assert.assertNotNull(vocabulary);
445 } catch (Exception e) {
446 throw new RuntimeException(e);
449 res.releaseConnection();
454 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
455 dependsOnMethods = {"read"})
456 public void readByName(String testName) throws Exception {
458 if (logger.isDebugEnabled()) {
459 logger.debug(testBanner(testName, CLASS_NAME));
464 // Submit the request to the service and store the response.
465 ClientResponse<MultipartInput> res = client.read(knownResourceId);
466 int statusCode = res.getStatus();
468 // Check the status code of the response: does it match
469 // the expected response(s)?
470 if(logger.isDebugEnabled()){
471 logger.debug(testName + ": status = " + statusCode);
473 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
474 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
475 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
476 //FIXME: remove the following try catch once Aron fixes signatures
478 MultipartInput input = (MultipartInput) res.getEntity();
479 VocabulariesCommon vocabulary = (VocabulariesCommon) extractPart(input,
480 client.getCommonPartName(), VocabulariesCommon.class);
481 Assert.assertNotNull(vocabulary);
482 } catch (Exception e) {
483 throw new RuntimeException(e);
488 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
489 dependsOnMethods = {"createItem", "read"})
490 public void readItem(String testName) throws Exception {
492 if (logger.isDebugEnabled()) {
493 logger.debug(testBanner(testName, CLASS_NAME));
498 // Submit the request to the service and store the response.
499 VocabularyClient client = new VocabularyClient();
500 ClientResponse<MultipartInput> res = client.readItem(knownResourceId, knownItemResourceId);
501 int statusCode = res.getStatus();
503 // Check the status code of the response: does it match
504 // the expected response(s)?
505 if(logger.isDebugEnabled()){
506 logger.debug(testName + ": status = " + statusCode);
508 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
509 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
510 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
512 // Check whether we've received a vocabulary item.
513 MultipartInput input = (MultipartInput) res.getEntity();
514 VocabularyitemsCommon vocabularyItem = (VocabularyitemsCommon) extractPart(input,
515 client.getItemCommonPartName(), VocabularyitemsCommon.class);
516 Assert.assertNotNull(vocabularyItem);
517 Assert.assertEquals(vocabularyItem.getInVocabulary(), knownResourceId);
521 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
522 dependsOnMethods = {"updateItem"})
523 public void verifyIllegalItemDisplayName(String testName) throws Exception {
525 if (logger.isDebugEnabled()) {
526 logger.debug(testBanner(testName, CLASS_NAME));
529 testSetup(STATUS_BAD_REQUEST, ServiceRequestType.UPDATE);
530 // setupUpdateWithWrongXmlSchema(testName);
532 // Submit the request to the service and store the response.
533 VocabularyClient client = new VocabularyClient();
534 ClientResponse<MultipartInput> res = client.readItem(knownResourceId, knownItemResourceId);
535 int statusCode = res.getStatus();
537 // Check the status code of the response: does it match
538 // the expected response(s)?
539 if(logger.isDebugEnabled()){
540 logger.debug(testName + ": status = " + statusCode);
542 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
543 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
544 Assert.assertEquals(statusCode, Response.Status.OK.getStatusCode());
546 // Check whether Person has expected displayName.
547 MultipartInput input = (MultipartInput) res.getEntity();
548 VocabularyitemsCommon vitem = (VocabularyitemsCommon) extractPart(input,
549 client.getItemCommonPartName(), VocabularyitemsCommon.class);
550 Assert.assertNotNull(vitem);
551 // Try to Update with null displayName
552 vitem.setDisplayName(null);
554 // Submit the updated resource to the service and store the response.
555 MultipartOutput output = new MultipartOutput();
556 OutputPart commonPart = output.addPart(vitem, MediaType.APPLICATION_XML_TYPE);
557 commonPart.getHeaders().add("label", client.getItemCommonPartName());
558 res = client.updateItem(knownResourceId, knownItemResourceId, output);
559 statusCode = res.getStatus();
561 // Check the status code of the response: does it match the expected response(s)?
562 if(logger.isDebugEnabled()){
563 logger.debug("updateItem: status = " + statusCode);
565 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
566 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
567 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE,
568 "Expecting invalid message because of null displayName.");
570 // Now try to Update with 1-char displayName (too short)
571 vitem.setDisplayName("a");
573 // Submit the updated resource to the service and store the response.
574 output = new MultipartOutput();
575 commonPart = output.addPart(vitem, MediaType.APPLICATION_XML_TYPE);
576 commonPart.getHeaders().add("label", client.getItemCommonPartName());
577 res = client.updateItem(knownResourceId, knownItemResourceId, output);
578 statusCode = res.getStatus();
580 // Check the status code of the response: does it match the expected response(s)?
581 if(logger.isDebugEnabled()){
582 logger.debug("updateItem: status = " + statusCode);
584 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
585 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
586 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE,
587 "Expecting invalid message because of 1-char displayName.");
591 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
592 dependsOnMethods = {"read"})
593 public void readNonExistent(String testName) {
595 if (logger.isDebugEnabled()) {
596 logger.debug(testBanner(testName, CLASS_NAME));
599 setupReadNonExistent();
601 // Submit the request to the service and store the response.
602 VocabularyClient client = new VocabularyClient();
603 ClientResponse<MultipartInput> res = client.read(NON_EXISTENT_ID);
604 int statusCode = res.getStatus();
606 // Check the status code of the response: does it match
607 // the expected response(s)?
608 if(logger.isDebugEnabled()){
609 logger.debug(testName + ": status = " + statusCode);
611 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
612 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
613 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
616 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
617 dependsOnMethods = {"readItem", "readNonExistent"})
618 public void readItemNonExistent(String testName) {
620 if (logger.isDebugEnabled()) {
621 logger.debug(testBanner(testName, CLASS_NAME));
624 setupReadNonExistent();
626 // Submit the request to the service and store the response.
627 VocabularyClient client = new VocabularyClient();
628 ClientResponse<MultipartInput> res = client.readItem(knownResourceId, NON_EXISTENT_ID);
629 int statusCode = res.getStatus();
631 // Check the status code of the response: does it match
632 // the expected response(s)?
633 if(logger.isDebugEnabled()){
634 logger.debug(testName + ": status = " + statusCode);
636 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
637 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
638 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
640 // ---------------------------------------------------------------
641 // CRUD tests : READ_LIST tests
642 // ---------------------------------------------------------------
646 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
647 dependsOnMethods = {"createList", "read"})
648 public void readList(String testName) throws Exception {
650 if (logger.isDebugEnabled()) {
651 logger.debug(testBanner(testName, CLASS_NAME));
656 // Submit the request to the service and store the response.
657 VocabularyClient client = new VocabularyClient();
658 ClientResponse<VocabulariesCommonList> res = client.readList();
659 VocabulariesCommonList list = res.getEntity();
660 int statusCode = res.getStatus();
662 // Check the status code of the response: does it match
663 // the expected response(s)?
664 if(logger.isDebugEnabled()){
665 logger.debug(testName + ": status = " + statusCode);
667 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
668 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
669 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
671 // Optionally output additional data about list members for debugging.
672 boolean iterateThroughList = false;
673 if (iterateThroughList && logger.isDebugEnabled()) {
674 List<VocabulariesCommonList.VocabularyListItem> items =
675 list.getVocabularyListItem();
677 for (VocabulariesCommonList.VocabularyListItem item : items) {
678 String csid = item.getCsid();
679 logger.debug(testName + ": list-item[" + i + "] csid=" +
681 logger.debug(testName + ": list-item[" + i + "] displayName=" +
682 item.getDisplayName());
683 logger.debug(testName + ": list-item[" + i + "] URI=" +
691 @Test(dependsOnMethods = {"createList", "readItem"})
692 public void readItemList() {
693 readItemList(knownResourceId);
696 private void readItemList(String vcsid) {
698 final String testName = "readItemList";
703 // Submit the request to the service and store the response.
704 VocabularyClient client = new VocabularyClient();
705 ClientResponse<VocabularyitemsCommonList> res =
706 client.readItemList(vcsid);
707 VocabularyitemsCommonList list = res.getEntity();
708 int statusCode = res.getStatus();
710 // Check the status code of the response: does it match
711 // the expected response(s)?
712 if(logger.isDebugEnabled()){
713 logger.debug(" " + testName + ": status = " + statusCode);
715 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
716 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
717 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
719 List<VocabularyitemsCommonList.VocabularyitemListItem> items =
720 list.getVocabularyitemListItem();
721 int nItemsReturned = items.size();
722 if(logger.isDebugEnabled()){
723 logger.debug(" " + testName + ": Expected "
724 + nItemsToCreateInList+" items; got: "+nItemsReturned);
726 Assert.assertEquals( nItemsReturned, nItemsToCreateInList);
728 // Optionally output additional data about list members for debugging.
729 boolean iterateThroughList = true;
730 if (iterateThroughList && logger.isDebugEnabled()) {
731 logger.debug(" " + testName + ": checking items");
733 for (VocabularyitemsCommonList.VocabularyitemListItem item : items) {
734 logger.debug(" " + testName + ": list-item[" + i + "] csid=" +
736 logger.debug(" " + testName + ": list-item[" + i + "] displayName=" +
737 item.getDisplayName());
738 logger.debug(" " + testName + ": list-item[" + i + "] URI=" +
747 // ---------------------------------------------------------------
748 // CRUD tests : UPDATE tests
749 // ---------------------------------------------------------------
752 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
753 dependsOnMethods = {"read"})
754 public void update(String testName) throws Exception {
756 if (logger.isDebugEnabled()) {
757 logger.debug(testBanner(testName, CLASS_NAME));
762 // Retrieve the contents of a resource to update.
763 VocabularyClient client = new VocabularyClient();
764 ClientResponse<MultipartInput> res =
765 client.read(knownResourceId);
766 if(logger.isDebugEnabled()){
767 logger.debug(testName + ": read status = " + res.getStatus());
769 Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE);
771 if(logger.isDebugEnabled()){
772 logger.debug("got Vocabulary to update with ID: " + knownResourceId);
774 MultipartInput input = (MultipartInput) res.getEntity();
775 VocabulariesCommon vocabulary = (VocabulariesCommon) extractPart(input,
776 client.getCommonPartName(), VocabulariesCommon.class);
777 Assert.assertNotNull(vocabulary);
779 // Update the contents of this resource.
780 vocabulary.setDisplayName("updated-" + vocabulary.getDisplayName());
781 vocabulary.setVocabType("updated-" + vocabulary.getVocabType());
782 if(logger.isDebugEnabled()){
783 logger.debug("to be updated Vocabulary");
784 logger.debug(objectAsXmlString(vocabulary, VocabulariesCommon.class));
787 // Submit the updated resource to the service and store the response.
788 MultipartOutput output = new MultipartOutput();
789 OutputPart commonPart = output.addPart(vocabulary, MediaType.APPLICATION_XML_TYPE);
790 commonPart.getHeaders().add("label", client.getCommonPartName());
791 res = client.update(knownResourceId, output);
792 int statusCode = res.getStatus();
794 // Check the status code of the response: does it match the expected response(s)?
795 if(logger.isDebugEnabled()){
796 logger.debug("update: status = " + statusCode);
798 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
799 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
800 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
802 // Retrieve the updated resource and verify that its contents exist.
803 input = (MultipartInput) res.getEntity();
804 VocabulariesCommon updatedVocabulary =
805 (VocabulariesCommon) extractPart(input,
806 client.getCommonPartName(), VocabulariesCommon.class);
807 Assert.assertNotNull(updatedVocabulary);
809 // Verify that the updated resource received the correct data.
810 Assert.assertEquals(updatedVocabulary.getDisplayName(),
811 vocabulary.getDisplayName(),
812 "Data in updated object did not match submitted data.");
815 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
816 dependsOnMethods = {"readItem", "update"})
817 public void updateItem(String testName) throws Exception {
819 if (logger.isDebugEnabled()) {
820 logger.debug(testBanner(testName, CLASS_NAME));
825 // Retrieve the contents of a resource to update.
826 VocabularyClient client = new VocabularyClient();
827 ClientResponse<MultipartInput> res =
828 client.readItem(knownResourceId, knownItemResourceId);
829 if(logger.isDebugEnabled()){
830 logger.debug(testName + ": read status = " + res.getStatus());
832 Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE);
834 if(logger.isDebugEnabled()){
835 logger.debug("got VocabularyItem to update with ID: " +
836 knownItemResourceId +
837 " in Vocab: " + knownResourceId );
839 MultipartInput input = (MultipartInput) res.getEntity();
840 VocabularyitemsCommon vocabularyItem = (VocabularyitemsCommon) extractPart(input,
841 client.getItemCommonPartName(), VocabularyitemsCommon.class);
842 Assert.assertNotNull(vocabularyItem);
844 // Update the contents of this resource.
845 vocabularyItem.setDisplayName("updated-" + vocabularyItem.getDisplayName());
846 if(logger.isDebugEnabled()){
847 logger.debug("to be updated VocabularyItem");
848 logger.debug(objectAsXmlString(vocabularyItem,
849 VocabularyitemsCommon.class));
852 // Submit the updated resource to the service and store the response.
853 MultipartOutput output = new MultipartOutput();
854 OutputPart commonPart = output.addPart(vocabularyItem, MediaType.APPLICATION_XML_TYPE);
855 commonPart.getHeaders().add("label", client.getItemCommonPartName());
856 res = client.updateItem(knownResourceId, knownItemResourceId, output);
857 int statusCode = res.getStatus();
859 // Check the status code of the response: does it match the expected response(s)?
860 if(logger.isDebugEnabled()){
861 logger.debug("updateItem: status = " + statusCode);
863 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
864 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
865 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
867 // Retrieve the updated resource and verify that its contents exist.
868 input = (MultipartInput) res.getEntity();
869 VocabularyitemsCommon updatedVocabularyItem =
870 (VocabularyitemsCommon) extractPart(input,
871 client.getItemCommonPartName(), VocabularyitemsCommon.class);
872 Assert.assertNotNull(updatedVocabularyItem);
874 // Verify that the updated resource received the correct data.
875 Assert.assertEquals(updatedVocabularyItem.getDisplayName(),
876 vocabularyItem.getDisplayName(),
877 "Data in updated VocabularyItem did not match submitted data.");
881 // Placeholders until the three tests below can be uncommented.
882 // See Issue CSPACE-401.
884 public void updateWithEmptyEntityBody(String testName) throws Exception {
888 public void updateWithMalformedXml(String testName) throws Exception {
892 public void updateWithWrongXmlSchema(String testName) throws Exception {
897 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
898 dependsOnMethods = {"create", "update", "testSubmitRequest"})
899 public void updateWithEmptyEntityBody(String testName) throws Exception {
901 if (logger.isDebugEnabled()) {
902 logger.debug(testBanner(testName, CLASS_NAME));
905 setupUpdateWithEmptyEntityBody();
907 // Submit the request to the service and store the response.
908 String method = REQUEST_TYPE.httpMethodName();
909 String url = getResourceURL(knownResourceId);
910 String mediaType = MediaType.APPLICATION_XML;
911 final String entity = "";
912 int statusCode = submitRequest(method, url, mediaType, entity);
914 // Check the status code of the response: does it match
915 // the expected response(s)?
916 if(logger.isDebugEnabled()){
917 logger.debug(testName + ": url=" + url +
918 " status=" + statusCode);
920 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
921 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
922 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
926 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
927 dependsOnMethods = {"create", "update", "testSubmitRequest"})
928 public void updateWithMalformedXml(String testName) throws Exception {
930 if (logger.isDebugEnabled()) {
931 logger.debug(testBanner(testName, CLASS_NAME));
934 setupUpdateWithMalformedXml();
936 // Submit the request to the service and store the response.
937 String method = REQUEST_TYPE.httpMethodName();
938 String url = getResourceURL(knownResourceId);
939 String mediaType = MediaType.APPLICATION_XML;
940 final String entity = MALFORMED_XML_DATA;
941 int statusCode = submitRequest(method, url, mediaType, entity);
943 // Check the status code of the response: does it match
944 // the expected response(s)?
945 if(logger.isDebugEnabled()){
946 logger.debug(testName + ": url=" + url +
947 " status=" + statusCode);
949 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
950 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
951 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
955 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTest.class,
956 dependsOnMethods = {"create", "update", "testSubmitRequest"})
957 public void updateWithWrongXmlSchema(String testName) throws Exception {
959 if (logger.isDebugEnabled()) {
960 logger.debug(testBanner(testName, CLASS_NAME));
963 setupUpdateWithWrongXmlSchema();
965 // Submit the request to the service and store the response.
966 String method = REQUEST_TYPE.httpMethodName();
967 String url = getResourceURL(knownResourceId);
968 String mediaType = MediaType.APPLICATION_XML;
969 final String entity = WRONG_XML_SCHEMA_DATA;
970 int statusCode = submitRequest(method, url, mediaType, entity);
972 // Check the status code of the response: does it match
973 // the expected response(s)?
974 if(logger.isDebugEnabled()){
975 logger.debug("updateWithWrongXmlSchema: url=" + url +
976 " status=" + statusCode);
978 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
979 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
980 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
986 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
987 dependsOnMethods = {"update", "testSubmitRequest"})
988 public void updateNonExistent(String testName) throws Exception {
990 if (logger.isDebugEnabled()) {
991 logger.debug(testBanner(testName, CLASS_NAME));
994 setupUpdateNonExistent();
996 // Submit the request to the service and store the response.
997 // Note: The ID used in this 'create' call may be arbitrary.
998 // The only relevant ID may be the one used in update(), below.
999 VocabularyClient client = new VocabularyClient();
1000 String displayName = "displayName-" + NON_EXISTENT_ID;
1001 MultipartOutput multipart = VocabularyClientUtils.createEnumerationInstance(
1002 displayName, NON_EXISTENT_ID, client.getCommonPartName());
1003 ClientResponse<MultipartInput> res =
1004 client.update(NON_EXISTENT_ID, multipart);
1005 int statusCode = res.getStatus();
1007 // Check the status code of the response: does it match
1008 // the expected response(s)?
1009 if(logger.isDebugEnabled()){
1010 logger.debug(testName + ": status = " + statusCode);
1012 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
1013 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
1014 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
1017 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
1018 dependsOnMethods = {"updateItem", "testItemSubmitRequest"})
1019 public void updateNonExistentItem(String testName) throws Exception {
1021 if (logger.isDebugEnabled()) {
1022 logger.debug(testBanner(testName, CLASS_NAME));
1025 setupUpdateNonExistent();
1027 // Submit the request to the service and store the response.
1028 // Note: The ID used in this 'create' call may be arbitrary.
1029 // The only relevant ID may be the one used in update(), below.
1030 VocabularyClient client = new VocabularyClient();
1031 HashMap<String, String> itemInfo = new HashMap<String, String>();
1032 itemInfo.put(VocabularyItemJAXBSchema.SHORT_IDENTIFIER, "nonex");
1033 itemInfo.put(VocabularyItemJAXBSchema.DISPLAY_NAME, "display-nonex");
1034 MultipartOutput multipart =
1035 VocabularyClientUtils.createVocabularyItemInstance(knownResourceId,
1036 VocabularyClientUtils.createVocabularyRefName(NON_EXISTENT_ID, null),
1037 itemInfo, client.getItemCommonPartName());
1038 ClientResponse<MultipartInput> res =
1039 client.updateItem(knownResourceId, NON_EXISTENT_ID, multipart);
1040 int statusCode = res.getStatus();
1042 // Check the status code of the response: does it match
1043 // the expected response(s)?
1044 if(logger.isDebugEnabled()){
1045 logger.debug(testName + ": status = " + statusCode);
1047 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
1048 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
1049 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
1052 // ---------------------------------------------------------------
1053 // CRUD tests : DELETE tests
1054 // ---------------------------------------------------------------
1057 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
1058 dependsOnMethods = {"create", "readList", "testSubmitRequest", "update"})
1059 public void delete(String testName) throws Exception {
1061 if (logger.isDebugEnabled()) {
1062 logger.debug(testBanner(testName, CLASS_NAME));
1067 // Submit the request to the service and store the response.
1068 VocabularyClient client = new VocabularyClient();
1069 ClientResponse<Response> res = client.delete(knownResourceId);
1070 int statusCode = res.getStatus();
1072 // Check the status code of the response: does it match
1073 // the expected response(s)?
1074 if(logger.isDebugEnabled()){
1075 logger.debug(testName + ": status = " + statusCode);
1077 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
1078 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
1079 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
1082 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
1083 dependsOnMethods = {"createItem", "readItemList", "testItemSubmitRequest",
1084 "updateItem", "verifyIllegalItemDisplayName"})
1085 public void deleteItem(String testName) throws Exception {
1087 if (logger.isDebugEnabled()) {
1088 logger.debug(testBanner(testName, CLASS_NAME));
1093 // Submit the request to the service and store the response.
1094 VocabularyClient client = new VocabularyClient();
1095 ClientResponse<Response> res = client.deleteItem(knownResourceId, knownItemResourceId);
1096 int statusCode = res.getStatus();
1098 // Check the status code of the response: does it match
1099 // the expected response(s)?
1100 if(logger.isDebugEnabled()){
1101 logger.debug("delete: status = " + statusCode);
1103 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
1104 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
1105 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
1110 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
1111 dependsOnMethods = {"delete"})
1112 public void deleteNonExistent(String testName) throws Exception {
1114 if (logger.isDebugEnabled()) {
1115 logger.debug(testBanner(testName, CLASS_NAME));
1118 setupDeleteNonExistent();
1120 // Submit the request to the service and store the response.
1121 VocabularyClient client = new VocabularyClient();
1122 ClientResponse<Response> res = client.delete(NON_EXISTENT_ID);
1123 int statusCode = res.getStatus();
1125 // Check the status code of the response: does it match
1126 // the expected response(s)?
1127 if(logger.isDebugEnabled()){
1128 logger.debug(testName + ": status = " + statusCode);
1130 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
1131 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
1132 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
1135 @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
1136 dependsOnMethods = {"deleteItem"})
1137 public void deleteNonExistentItem(String testName) {
1139 if (logger.isDebugEnabled()) {
1140 logger.debug(testBanner(testName, CLASS_NAME));
1143 setupDeleteNonExistent();
1145 // Submit the request to the service and store the response.
1146 VocabularyClient client = new VocabularyClient();
1147 ClientResponse<Response> res = client.deleteItem(knownResourceId, NON_EXISTENT_ID);
1148 int statusCode = res.getStatus();
1150 // Check the status code of the response: does it match
1151 // the expected response(s)?
1152 if(logger.isDebugEnabled()){
1153 logger.debug(testName + ": status = " + statusCode);
1155 Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
1156 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
1157 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
1160 // ---------------------------------------------------------------
1161 // Utility tests : tests of code used in tests above
1162 // ---------------------------------------------------------------
1164 * Tests the code for manually submitting data that is used by several
1165 * of the methods above.
1167 @Test(dependsOnMethods = {"create", "read"})
1168 public void testSubmitRequest() {
1170 // Expected status code: 200 OK
1173 // Submit the request to the service and store the response.
1174 String method = ServiceRequestType.READ.httpMethodName();
1175 String url = getResourceURL(knownResourceId);
1176 int statusCode = submitRequest(method, url);
1178 // Check the status code of the response: does it match
1179 // the expected response(s)?
1180 if(logger.isDebugEnabled()){
1181 logger.debug("testSubmitRequest: url=" + url +
1182 " status=" + statusCode);
1184 Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
1188 @Test(dependsOnMethods = {"createItem", "readItem", "testSubmitRequest"})
1189 public void testItemSubmitRequest() {
1191 // Expected status code: 200 OK
1192 final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
1194 // Submit the request to the service and store the response.
1195 String method = ServiceRequestType.READ.httpMethodName();
1196 String url = getItemResourceURL(knownResourceId, knownItemResourceId);
1197 int statusCode = submitRequest(method, url);
1199 // Check the status code of the response: does it match
1200 // the expected response(s)?
1201 if(logger.isDebugEnabled()){
1202 logger.debug("testItemSubmitRequest: url=" + url +
1203 " status=" + statusCode);
1205 Assert.assertEquals(statusCode, EXPECTED_STATUS);
1209 // ---------------------------------------------------------------
1210 // Cleanup of resources created during testing
1211 // ---------------------------------------------------------------
1214 * Deletes all resources created by tests, after all tests have been run.
1216 * This cleanup method will always be run, even if one or more tests fail.
1217 * For this reason, it attempts to remove all resources created
1218 * at any point during testing, even if some of those resources
1219 * may be expected to be deleted by certain tests.
1221 @AfterClass(alwaysRun=true)
1222 public void cleanUp() {
1223 String noTest = System.getProperty("noTestCleanup");
1224 if(Boolean.TRUE.toString().equalsIgnoreCase(noTest)) {
1225 if (logger.isDebugEnabled()) {
1226 logger.debug("Skipping Cleanup phase ...");
1230 if (logger.isDebugEnabled()) {
1231 logger.debug("Cleaning up temporary resources created for testing ...");
1233 VocabularyClient client = new VocabularyClient();
1234 String vocabularyResourceId;
1235 String vocabularyItemResourceId;
1236 // Clean up vocabulary item resources.
1237 for (Map.Entry<String, String> entry : allResourceItemIdsCreated.entrySet()) {
1238 vocabularyItemResourceId = entry.getKey();
1239 vocabularyResourceId = entry.getValue();
1240 // Note: Any non-success responses are ignored and not reported.
1241 client.deleteItem(vocabularyResourceId, vocabularyItemResourceId).releaseConnection();
1243 // Clean up vocabulary resources.
1244 for (String resourceId : allResourceIdsCreated) {
1245 // Note: Any non-success responses are ignored and not reported.
1246 client.delete(resourceId).releaseConnection();
1251 // ---------------------------------------------------------------
1252 // Utility methods used by tests above
1253 // ---------------------------------------------------------------
1255 public String getServicePathComponent() {
1256 return SERVICE_PATH_COMPONENT;
1259 public String getItemServicePathComponent() {
1260 return ITEM_SERVICE_PATH_COMPONENT;
1264 * Returns the root URL for a service.
1266 * This URL consists of a base URL for all services, followed by
1267 * a path component for the owning vocabulary, followed by the
1268 * path component for the items.
1270 * @return The root URL for a service.
1272 protected String getItemServiceRootURL(String parentResourceIdentifier) {
1273 return getResourceURL(parentResourceIdentifier) + "/" + getItemServicePathComponent();
1277 * Returns the URL of a specific resource managed by a service, and
1278 * designated by an identifier (such as a universally unique ID, or UUID).
1280 * @param resourceIdentifier An identifier (such as a UUID) for a resource.
1282 * @return The URL of a specific resource managed by a service.
1284 protected String getItemResourceURL(String parentResourceIdentifier, String resourceIdentifier) {
1285 return getItemServiceRootURL(parentResourceIdentifier) + "/" + resourceIdentifier;