]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-6007: Added client tests to the Citation Authority service, based on Concept...
authorAron Roberts <aron@socrates.berkeley.edu>
Thu, 23 May 2013 00:53:32 +0000 (17:53 -0700)
committerAron Roberts <aron@socrates.berkeley.edu>
Thu, 23 May 2013 00:53:32 +0000 (17:53 -0700)
services/citation/client/src/main/java/org/collectionspace/services/client/CitationAuthorityClientUtils.java
services/citation/client/src/test/java/org/collectionspace/services/client/test/CitationAuthorityServiceTest.java [new file with mode: 0644]

index c2eb57e8bef7cf2c299dd50765b0f2e9a6062091..30c54f5c062bb6efefc8e2f2485dc3a88d4f2075 100644 (file)
-/**    
- * CitationAuthorityClientUtils.java
- *
- * {Purpose of This Class}
- *
- * {Other Notes Relating to This Class (Optional)}
- *
- * $LastChangedBy: $
- * $LastChangedRevision: $
- * $LastChangedDate: $
- *
- * This document is a part of the source code and related artifacts
- * for CollectionSpace, an open source collections management system
- * for museums and related institutions:
- *
- * http://www.collectionspace.org
- * http://wiki.collectionspace.org
- *
- * Copyright © 2009 {Contributing Institution}
- *
- * Licensed under the Educational Community License (ECL), Version 2.0.
- * You may not use this file except in compliance with this License.
- *
- * You may obtain a copy of the ECL 2.0 License at
- * https://source.collectionspace.org/collection-space/LICENSE.txt
- */
 package org.collectionspace.services.client;
 
-import java.util.*;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
 
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
 
-import org.collectionspace.services.CitationJAXBSchema;
-import org.collectionspace.services.client.test.ServiceRequestType;
-import org.collectionspace.services.common.api.Tools;
+import org.apache.commons.io.FileUtils;
 import org.collectionspace.services.citation.CitationTermGroup;
-import org.collectionspace.services.citation.CitationTermGroupList;
-import org.collectionspace.services.citation.CitationsCommon;
 import org.collectionspace.services.citation.CitationauthoritiesCommon;
+import org.collectionspace.services.client.test.ServiceRequestType;
+import org.collectionspace.services.common.api.Tools;
+import org.dom4j.DocumentException;
 import org.jboss.resteasy.client.ClientResponse;
-//import org.jboss.resteasy.plugins.providers.multipart.OutputPart;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.collectionspace.services.citation.StructuredDateGroup;
 
-/**
- * The Class CitationAuthorityClientUtils.
- */
 public class CitationAuthorityClientUtils {
-    
-    /** The Constant logger. */
     private static final Logger logger =
         LoggerFactory.getLogger(CitationAuthorityClientUtils.class);
-       private static final ServiceRequestType READ_REQ = ServiceRequestType.READ;
-
-    /**
-     * @param csid the id of the CitationAuthority
-     * @param client if null, creates a new client
-     * @return
-     */
-    public static String getAuthorityRefName(String csid, CitationAuthorityClient client){
-       if (client == null) {
-               client = new CitationAuthorityClient();
-       }
-        ClientResponse<String> res = client.read(csid);
-        try {
-               int statusCode = res.getStatus();
-               if(!READ_REQ.isValidStatusCode(statusCode)
-                       ||(statusCode != CollectionSpaceClientUtils.STATUS_OK)) {
-                       throw new RuntimeException("Invalid status code returned: "+statusCode);
-               }
-               //FIXME: remove the following try catch once Aron fixes signatures
-               try {
-                   PoxPayloadIn input = new PoxPayloadIn(res.getEntity());
-                   CitationauthoritiesCommon citationAuthority = 
-                       (CitationauthoritiesCommon) CollectionSpaceClientUtils.extractPart(input,
-                           client.getCommonPartName(), CitationauthoritiesCommon.class);
-                       if(citationAuthority == null) {
-                               throw new RuntimeException("Null citationAuthority returned from service.");
-                       }
-                   return citationAuthority.getRefName();
-               } catch (Exception e) {
-                   throw new RuntimeException(e);
-               }
-        } finally {
-               res.releaseConnection();
-        }
-    }
-
-    /**
-     * @param csid the id of the CitationAuthority
-     * @param client if null, creates a new client
-     * @return
-     */
-    public static String getCitationRefName(String inAuthority, String csid, CitationAuthorityClient client){
-       if ( client == null) {
-               client = new CitationAuthorityClient();
-       }
-        ClientResponse<String> res = client.readItem(inAuthority, csid);
-        try {
-               int statusCode = res.getStatus();
-               if(!READ_REQ.isValidStatusCode(statusCode)
-                               ||(statusCode != CollectionSpaceClientUtils.STATUS_OK)) {
-                       throw new RuntimeException("Invalid status code returned: "+statusCode);
-               }
-               //FIXME: remove the following try catch once Aron fixes signatures
-               try {
-                   PoxPayloadIn input = new PoxPayloadIn(res.getEntity());
-                   CitationsCommon citation = 
-                       (CitationsCommon) CollectionSpaceClientUtils.extractPart(input,
-                           client.getItemCommonPartName(), CitationsCommon.class);
-                       if (citation == null) {
-                               throw new RuntimeException("Null citation returned from service.");
-                       }
-                   return citation.getRefName();
-               } catch (Exception e) {
-                   throw new RuntimeException(e);
-               }
-        } finally {
-               res.releaseConnection();
-        }
-    }
+    private static final String CITATION_VOCAB_TYPE = "CitationAuthority";
 
     /**
-     * Creates the citation authority instance.
-     *
-     * @param displayName the display name
-     * @param shortIdentifier the short Id 
-     * @param headerLabel the header label
-     * @return the multipart output
+     * Creates a new Citation Authority
+     * @param displayName      The displayName used in UI, etc.
+     * @param refName          The proper refName for this authority
+     * @param headerLabel      The common part label
+     * @return The PoxPayloadOut payload for the create call
      */
     public static PoxPayloadOut createCitationAuthorityInstance(
                String displayName, String shortIdentifier, String headerLabel ) {
         CitationauthoritiesCommon citationAuthority = new CitationauthoritiesCommon();
         citationAuthority.setDisplayName(displayName);
         citationAuthority.setShortIdentifier(shortIdentifier);
-        //String refName = createCitationAuthRefName(shortIdentifier, displayName);
-        //citationAuthority.setRefName(refName);
-        citationAuthority.setVocabType("CitationAuthority");
+        citationAuthority.setVocabType(CITATION_VOCAB_TYPE); //FIXME: REM - Should this really be hard-coded?
         PoxPayloadOut multipart = new PoxPayloadOut(CitationAuthorityClient.SERVICE_PAYLOAD_NAME);
         PayloadOutputPart commonPart = multipart.addPart(citationAuthority, MediaType.APPLICATION_XML_TYPE);
         commonPart.setLabel(headerLabel);
@@ -152,172 +50,78 @@ public class CitationAuthorityClientUtils {
     }
 
     /**
-     * Creates a citation instance.
-     *
-     * @param inAuthority the owning authority
-     * @param citationAuthRefName the owning Authority ref name
-     * @param citationInfo the citation info
-     * @param headerLabel the header label
-     * @return the multipart output
+     * @param commonPartXML the XML payload for the common part.
+     * @param headerLabel      The common part label
+     * @return The PoxPayloadOut payload for the create call
+     * @throws DocumentException
      */
-    public static PoxPayloadOut createCitationInstance(String inAuthority,
-               String citationAuthRefName,
-               Map<String, String> citationInfo,
-                List<CitationTermGroup> terms,
-               String headerLabel){
-        if (terms == null || terms.isEmpty()) {
-            terms = getTermGroupInstance(getGeneratedIdentifier());
-        }
-        final Map<String, List<String>> EMPTY_CITATION_REPEATABLES_INFO =
-                new HashMap<String, List<String>>();
-        return createCitationInstance(inAuthority, null /*citationAuthRefName*/,
-                citationInfo, terms, EMPTY_CITATION_REPEATABLES_INFO, headerLabel);
-    }
-
-    /**
-     * Creates a citation instance.
-     *
-     * @param inAuthority the owning authority
-     * @param citationAuthRefName the owning Authority ref name
-     * @param citationInfo the citation info
-     * @param terms a list of Citation terms
-     * @param citationRepeatablesInfo names and values of repeatable scalar fields in the Citation record
-     * @param headerLabel the header label
-     * @return the multipart output
-     */
-    public static PoxPayloadOut createCitationInstance(String inAuthority, 
-               String citationAuthRefName, Map<String, String> citationInfo,
-                List<CitationTermGroup> terms,
-                Map<String, List<String>> citationRepeatablesInfo, String headerLabel){
-        CitationsCommon citation = new CitationsCommon();
-        citation.setInAuthority(inAuthority);
-       String shortId = citationInfo.get(CitationJAXBSchema.SHORT_IDENTIFIER);
-       if (shortId == null || shortId.isEmpty()) {
-               throw new IllegalArgumentException("shortIdentifier cannot be null or empty");
-       }       
-       citation.setShortIdentifier(shortId);
-       
-       String value;
-        List<String> values = null;
-        
-        // Set values in the Term Information Group
-        CitationTermGroupList termList = new CitationTermGroupList();
-        if (terms == null || terms.isEmpty()) {
-            terms = getTermGroupInstance(getGeneratedIdentifier());
-        }
-        termList.getCitationTermGroup().addAll(terms); 
-        citation.setCitationTermGroupList(termList);               
-        
+    public static PoxPayloadOut createCitationInstance(
+               String commonPartXML, String headerLabel)  throws DocumentException {
         PoxPayloadOut multipart = new PoxPayloadOut(CitationAuthorityClient.SERVICE_ITEM_PAYLOAD_NAME);
-        PayloadOutputPart commonPart = multipart.addPart(citation,
+        /*
+        PayloadOutputPart commonPart = multipart.addPart(commonPartXML,
             MediaType.APPLICATION_XML_TYPE);
         commonPart.setLabel(headerLabel);
+        */
+        PayloadOutputPart commonPart = multipart.addPart(
+                       CitationAuthorityClient.SERVICE_ITEM_COMMON_PART_NAME,
+                       commonPartXML);
 
         if(logger.isDebugEnabled()){
-               logger.debug("to be created, citation common ", citation, CitationsCommon.class);
+               logger.debug("to be created, citation common ", commonPart.asXML());
         }
 
         return multipart;
     }
     
-    /**
-     * Creates the item in authority.
-     *
-     * @param vcsid the vcsid
-     * @param citationAuthorityRefName the citation authority ref name
-     * @param citationMap the citation map. CitationJAXBSchema.SHORT_IDENTIFIER is REQUIRED.
-     * @param client the client
-     * @return the string
-     */
-    public static String createItemInAuthority(String vcsid, 
-               String citationAuthorityRefName, Map<String,String> citationMap,
-                List<CitationTermGroup> terms, Map<String, List<String>> citationRepeatablesMap,
-                CitationAuthorityClient client ) {
+    public static String createItemInAuthority(String vcsid,
+               String commonPartXML,
+               CitationAuthorityClient client ) throws DocumentException {
        // Expected status code: 201 Created
        int EXPECTED_STATUS_CODE = Response.Status.CREATED.getStatusCode();
        // Type of service request being tested
        ServiceRequestType REQUEST_TYPE = ServiceRequestType.CREATE;
-        
-        String displayName = "";
-        if (terms !=null && terms.size() > 0) {
-            displayName = terms.get(0).getTermDisplayName();
-        }
        
-       if(logger.isDebugEnabled()){
-               logger.debug("Creating item with display name: \"" + displayName
-                               +"\" in citationAuthority: \"" + vcsid +"\"");
-       }
        PoxPayloadOut multipart = 
-               createCitationInstance(vcsid, null /*citationAuthorityRefName*/,
-                       citationMap, terms, citationRepeatablesMap, client.getItemCommonPartName());
-       
-       String result = null;
+               createCitationInstance(commonPartXML, client.getItemCommonPartName());
+       String newID = null;
        ClientResponse<Response> res = client.createItem(vcsid, multipart);
-       try {
+        try {
                int statusCode = res.getStatus();
        
                if(!REQUEST_TYPE.isValidStatusCode(statusCode)) {
-                       throw new RuntimeException("Could not create Item: \""+citationMap.get(CitationJAXBSchema.SHORT_IDENTIFIER)
-                                       +"\" in citationAuthority: \"" + vcsid //citationAuthorityRefName
+                       throw new RuntimeException("Could not create Item: \""+commonPartXML
+                                       +"\" in citationAuthority: \"" + vcsid
                                        +"\" "+ invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
                }
                if(statusCode != EXPECTED_STATUS_CODE) {
-                       throw new RuntimeException("Unexpected Status when creating Item: \""+citationMap.get(CitationJAXBSchema.SHORT_IDENTIFIER)
-                                       +"\" in citationAuthority: \"" + vcsid /*citationAuthorityRefName*/ +"\", Status:"+ statusCode);
+                       throw new RuntimeException("Unexpected Status when creating Item: \""+commonPartXML
+                                       +"\" in citationAuthority: \"" + vcsid +"\", Status:"+ statusCode);
                }
-       
-               result = extractId(res);
-       } finally {
-               res.releaseConnection();
-       }
-       
-       return result;
-    }
+               newID = extractId(res);
+        } finally {
+               res.releaseConnection();
+        }
 
-    /**
-     * Creates the citationAuthority ref name.
-     *
-     * @param shortId the citationAuthority shortIdentifier
-     * @param displaySuffix displayName to be appended, if non-null
-     * @return the string
-     */
-    /*
-    public static String createCitationAuthRefName(String shortId, String displaySuffix) {
-       String refName = "urn:cspace:org.collectionspace.demo:citationauthority:name("
-                       +shortId+")";
-       if(displaySuffix!=null&&!displaySuffix.isEmpty())
-               refName += "'"+displaySuffix+"'";
-       return refName;
+       return newID;
     }
-    */
-
+    
     /**
-     * Creates the citation ref name.
+     * Creates an item in the authority from an XML file.
      *
-     * @param citationAuthRefName the citation auth ref name
-     * @param shortId the citation shortIdentifier
-     * @param displaySuffix displayName to be appended, if non-null
-     * @return the string
+     * @param fileName the file name
+     * @return new CSID as string
+     * @throws Exception the exception
      */
-    /*
-    public static String createCitationRefName(
-                                               String citationAuthRefName, String shortId, String displaySuffix) {
-       String refName = citationAuthRefName+":citation:name("+shortId+")";
-       if(displaySuffix!=null&&!displaySuffix.isEmpty())
-               refName += "'"+displaySuffix+"'";
-       return refName;
-    }
-    */
+    private String createItemInAuthorityFromXmlFile(String vcsid, String commonPartFileName, 
+               CitationAuthorityClient client) throws Exception {
+        byte[] b = FileUtils.readFileToByteArray(new File(commonPartFileName));
+        String commonPartXML = new String(b);
+       return createItemInAuthority(vcsid, commonPartXML, client );
+    }    
 
-    /**
-     * Extract id.
-     *
-     * @param res the res
-     * @return the string
-     */
     public static String extractId(ClientResponse<Response> res) {
         MultivaluedMap<String, Object> mvm = res.getMetadata();
-        // FIXME: This may throw an NPE if the Location: header isn't present
         String uri = (String) ((ArrayList<Object>) mvm.get("Location")).get(0);
         if(logger.isDebugEnabled()){
                logger.debug("extractId:uri=" + uri);
@@ -346,62 +150,8 @@ public class CitationAuthorityClientUtils {
         return "Status code '" + statusCode + "' in response is NOT within the expected set: " +
                 requestType.validStatusCodesAsString();
     }
-
-
-    
-    /**
-     * Produces a default displayName from the basic name and dates fields.
-     * @see CitationDocumentModelHandler.prepareDefaultDisplayName() which
-     * duplicates this logic, until we define a service-general utils package
-     * that is neither client nor service specific.
-     * @param foreName 
-     * @param middleName
-     * @param surName
-     * @param birthDate
-     * @param deathDate
-     * @return display name
-     */
-    public static String prepareDefaultDisplayName(
-               String foreName, String middleName, String surName, 
-            String birthDate, String deathDate) {
-       StringBuilder newStr = new StringBuilder();
-               final String sep = " ";
-               final String dateSep = "-";
-               List<String> nameStrings = 
-                       Arrays.asList(foreName, middleName, surName);
-               boolean firstAdded = false;
-       for(String partStr : nameStrings ){
-                       if(null != partStr ) {
-                               if(firstAdded) {
-                                       newStr.append(sep);
-                               }
-                               newStr.append(partStr);
-                               firstAdded = true;
-                       }
-       }
-       // Now we add the dates. In theory could have dates with no name, but that is their problem.
-       boolean foundBirth = false;
-        if(null != birthDate) {
-         if(firstAdded) {
-             newStr.append(sep);
-         }
-         newStr.append(birthDate);
-                 newStr.append(dateSep);     // Put this in whether there is a death date or not
-         foundBirth = true;
-        }
-        if(null != deathDate) {
-         if(!foundBirth) {
-             if(firstAdded) {
-                 newStr.append(sep);
-             }
-             newStr.append(dateSep);
-         }
-         newStr.append(deathDate);
-        }
-               return newStr.toString();
-    }
     
-    public static List<CitationTermGroup> getTermGroupInstance(String identifier) {
+     public static List<CitationTermGroup> getTermGroupInstance(String identifier) {
         if (Tools.isBlank(identifier)) {
             identifier = getGeneratedIdentifier();
         }
diff --git a/services/citation/client/src/test/java/org/collectionspace/services/client/test/CitationAuthorityServiceTest.java b/services/citation/client/src/test/java/org/collectionspace/services/client/test/CitationAuthorityServiceTest.java
new file mode 100644 (file)
index 0000000..77d06ab
--- /dev/null
@@ -0,0 +1,447 @@
+/**
+ * This document is a part of the source code and related artifacts for
+ * CollectionSpace, an open source collections management system for museums and
+ * related institutions:
+ *
+ * http://www.collectionspace.org http://wiki.collectionspace.org
+ *
+ * Copyright (c)) 2009 Regents of the University of California
+ *
+ * Licensed under the Educational Community License (ECL), Version 2.0. You may
+ * not use this file except in compliance with this License.
+ *
+ * You may obtain a copy of the ECL 2.0 License at
+ * https://source.collectionspace.org/collection-space/LICENSE.txt
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.collectionspace.services.client.test;
+
+import java.util.List;
+import java.util.Map;
+import org.collectionspace.services.CitationJAXBSchema;
+import org.collectionspace.services.citation.CitationTermGroup;
+import org.collectionspace.services.citation.CitationTermGroupList;
+import org.collectionspace.services.citation.CitationauthoritiesCommon;
+import org.collectionspace.services.citation.CitationsCommon;
+import org.collectionspace.services.client.AbstractCommonListUtils;
+import org.collectionspace.services.client.AuthorityClient;
+import org.collectionspace.services.client.CollectionSpaceClient;
+import org.collectionspace.services.client.CitationAuthorityClient;
+import org.collectionspace.services.client.CitationAuthorityClientUtils;
+import org.collectionspace.services.client.PoxPayloadOut;
+import org.collectionspace.services.common.api.GregorianCalendarDateTimeUtils;
+import org.collectionspace.services.jaxb.AbstractCommonList;
+import org.dom4j.DocumentException;
+import org.jboss.resteasy.client.ClientResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.Test;
+
+/**
+ * ConceptAuthorityServiceTest, carries out tests against a deployed and running
+ * ConceptAuthority Service.
+ *
+ * $LastChangedRevision: 753 $ $LastChangedDate: 2009-09-23 11:03:36 -0700 (Wed,
+ * 23 Sep 2009) $
+ */
+public class CitationAuthorityServiceTest extends AbstractAuthorityServiceTest<CitationauthoritiesCommon, CitationsCommon> {
+
+    /**
+     * The logger.
+     */
+    private final String CLASS_NAME = CitationAuthorityServiceTest.class.getName();
+    private final Logger logger = LoggerFactory.getLogger(CitationAuthorityServiceTest.class);
+    private final static String CURRENT_DATE_UTC =
+            GregorianCalendarDateTimeUtils.currentDateUTC();
+    // Instance variables specific to this test.
+    final String TEST_NAME = "Citation 1";
+    final String TEST_SHORTID = "citation1";
+    final String TEST_SCOPE_NOTE = "A representative citation";
+    // TODO Make status type be a controlled vocab term.
+    final String TEST_STATUS = "Approved";
+
+    @Override
+    public String getServicePathComponent() {
+        return CitationAuthorityClient.SERVICE_PATH_COMPONENT;
+    }
+
+    @Override
+    protected String getServiceName() {
+        return CitationAuthorityClient.SERVICE_NAME;
+    }
+
+    public String getItemServicePathComponent() {
+        return AuthorityClient.ITEMS;
+    }
+
+    /* (non-Javadoc)
+     * @see org.collectionspace.services.client.test.BaseServiceTest#getClientInstance()
+     */
+    @Override
+    protected CollectionSpaceClient getClientInstance() {
+        return new CitationAuthorityClient();
+    }
+
+    /**
+     * Creates an item in an authority.
+     *
+     * @param authorityId an identifier for the authority item
+     * @return the string
+     */
+    @Override
+    protected String createItemInAuthority(String authorityId) {
+
+        final String testName = "createItemInAuthority(" + authorityId + ")";
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName);
+        }
+
+        // Submit the request to the service and store the response.
+        CitationAuthorityClient client = new CitationAuthorityClient();
+
+        String commonPartXML = createCommonPartXMLForItem(TEST_SHORTID, TEST_NAME);
+
+        String newID;
+        try {
+            newID = CitationAuthorityClientUtils.createItemInAuthority(authorityId,
+                    commonPartXML, client);
+        } catch (Exception e) {
+            logger.error("Problem creating item from XML: " + e.getLocalizedMessage());
+            logger.debug("commonPartXML: " + commonPartXML);
+            return null;
+        }
+
+        // Store the ID returned from the first item resource created
+        // for additional tests below.
+        if (knownItemResourceId == null) {
+            setKnownItemResource(newID, TEST_SHORTID);
+            if (logger.isDebugEnabled()) {
+                logger.debug(testName + ": knownItemResourceId=" + newID);
+            }
+        }
+
+        // Store the IDs from any item resources created
+        // by tests, along with the IDs of their parents, so these items
+        // can be deleted after all tests have been run.
+        allResourceItemIdsCreated.put(newID, authorityId);
+
+        return newID;
+    }
+
+    /**
+     * Read item list.
+     */
+    @Test(dataProvider = "testName", groups = {"readList"},
+            dependsOnMethods = {"readList"})
+    public void readItemList(String testName) {
+        readItemList(knownAuthorityWithItems, null);
+    }
+
+    /**
+     * Read item list by authority name.
+     */
+    @Test(dataProvider = "testName", groups = {"readList"},
+            dependsOnMethods = {"readItemList"})
+    public void readItemListByAuthorityName(String testName) {
+        readItemList(null, READITEMS_SHORT_IDENTIFIER);
+    }
+
+    /**
+     * Read item list.
+     *
+     * @param vcsid the vcsid
+     * @param name the name
+     */
+    private void readItemList(String vcsid, String shortId) {
+
+        String testName = "readItemList";
+
+        // Perform setup.
+        setupReadList();
+
+        // Submit the request to the service and store the response.
+        CitationAuthorityClient client = new CitationAuthorityClient();
+        ClientResponse<AbstractCommonList> res = null;
+        if (vcsid != null) {
+            res = client.readItemList(vcsid, null, null);
+        } else if (shortId != null) {
+            res = client.readItemListForNamedAuthority(shortId, null, null);
+        } else {
+            Assert.fail("readItemList passed null csid and name!");
+        }
+        AbstractCommonList list = null;
+        try {
+            assertStatusCode(res, testName);
+            list = res.getEntity();
+        } finally {
+            res.releaseConnection();
+        }
+        List<AbstractCommonList.ListItem> items =
+                list.getListItem();
+        int nItemsReturned = items.size();
+        // There will be 'nItemsToCreateInList'
+        // items created by the createItemList test,
+        // all associated with the same parent resource.
+        int nExpectedItems = nItemsToCreateInList;
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + ": Expected "
+                    + nExpectedItems + " items; got: " + nItemsReturned);
+        }
+        Assert.assertEquals(nItemsReturned, nExpectedItems);
+
+        for (AbstractCommonList.ListItem item : items) {
+            String value =
+                    AbstractCommonListUtils.ListItemGetElementValue(item, CitationJAXBSchema.REF_NAME);
+            Assert.assertTrue((null != value), "Item refName is null!");
+            value =
+                    AbstractCommonListUtils.ListItemGetElementValue(item, CitationJAXBSchema.TERM_DISPLAY_NAME);
+            Assert.assertTrue((null != value), "Item termDisplayName is null!");
+        }
+        if (logger.isTraceEnabled()) {
+            AbstractCommonListUtils.ListItemsInAbstractCommonList(list, logger, testName);
+        }
+    }
+
+    @Override
+    public void delete(String testName) throws Exception {
+        // Do nothing.  See localDelete().  This ensure proper test order.
+    }
+
+    @Test(dataProvider = "testName", dependsOnMethods = {"localDeleteItem"})
+    public void localDelete(String testName) throws Exception {
+        super.delete(testName);
+    }
+
+    @Override
+    public void deleteItem(String testName) throws Exception {
+        // Do nothing.  We need to wait until after the test "localDelete" gets run.  When it does,
+        // its dependencies will get run first and then we can call the base class' delete method.
+    }
+
+    @Test(dataProvider = "testName", groups = {"delete"},
+            dependsOnMethods = {"readItem", "updateItem"})
+    public void localDeleteItem(String testName) throws Exception {
+        super.deleteItem(testName);
+    }
+
+    // ---------------------------------------------------------------
+    // Cleanup of resources created during testing
+    // ---------------------------------------------------------------
+    /**
+     * Deletes all resources created by tests, after all tests have been run.
+     *
+     * This cleanup method will always be run, even if one or more tests fail.
+     * For this reason, it attempts to remove all resources created at any point
+     * during testing, even if some of those resources may be expected to be
+     * deleted by certain tests.
+     */
+    @AfterClass(alwaysRun = true)
+    public void cleanUp() {
+        String noTest = System.getProperty("noTestCleanup");
+        if (Boolean.TRUE.toString().equalsIgnoreCase(noTest)) {
+            if (logger.isDebugEnabled()) {
+                logger.debug("Skipping Cleanup phase ...");
+            }
+            return;
+        }
+        if (logger.isDebugEnabled()) {
+            logger.debug("Cleaning up temporary resources created for testing ...");
+        }
+        String parentResourceId;
+        String itemResourceId;
+        // Clean up contact resources.
+        CitationAuthorityClient client = new CitationAuthorityClient();
+        parentResourceId = knownResourceId;
+        // Clean up item resources.
+        for (Map.Entry<String, String> entry : allResourceItemIdsCreated.entrySet()) {
+            itemResourceId = entry.getKey();
+            parentResourceId = entry.getValue();
+            // Note: Any non-success responses from the delete operation
+            // below are ignored and not reported.
+            client.deleteItem(parentResourceId, itemResourceId).releaseConnection();
+        }
+        // Clean up parent resources.
+        for (String resourceId : allResourceIdsCreated) {
+            // Note: Any non-success responses from the delete operation
+            // below are ignored and not reported.
+            client.delete(resourceId).releaseConnection();
+        }
+    }
+
+    // ---------------------------------------------------------------
+    // Utility methods used by tests above
+    // ---------------------------------------------------------------
+   /* (non-Javadoc)
+     * @see org.collectionspace.services.client.test.BaseServiceTest#getServicePathComponent()
+     */
+    /**
+     * Returns the root URL for the item service.
+     *
+     * This URL consists of a base URL for all services, followed by a path
+     * component for the owning parent, followed by the path component for the
+     * items.
+     *
+     * @param parentResourceIdentifier An identifier (such as a UUID) for the
+     * parent authority resource of the relevant item resource.
+     *
+     * @return The root URL for the item service.
+     */
+    protected String getItemServiceRootURL(String parentResourceIdentifier) {
+        return getResourceURL(parentResourceIdentifier) + "/" + getItemServicePathComponent();
+    }
+
+    /**
+     * Returns the URL of a specific item resource managed by a service, and
+     * designated by an identifier (such as a universally unique ID, or UUID).
+     *
+     * @param parentResourceIdentifier An identifier (such as a UUID) for the
+     * parent authority resource of the relevant item resource.
+     *
+     * @param itemResourceIdentifier An identifier (such as a UUID) for an item
+     * resource.
+     *
+     * @return The URL of a specific item resource managed by a service.
+     */
+    protected String getItemResourceURL(String parentResourceIdentifier, String itemResourceIdentifier) {
+        return getItemServiceRootURL(parentResourceIdentifier) + "/" + itemResourceIdentifier;
+    }
+
+    @Override
+    public void authorityTests(String testName) {
+        // TODO Auto-generated method stub
+    }
+
+    //
+    // Concept specific overrides
+    //
+    @Override
+    protected PoxPayloadOut createInstance(String commonPartName,
+            String identifier) {
+        CitationAuthorityClient client = new CitationAuthorityClient();
+        String shortId = identifier;
+        String displayName = "displayName-" + shortId;
+        PoxPayloadOut multipart =
+                CitationAuthorityClientUtils.createCitationAuthorityInstance(
+                displayName, shortId, commonPartName);
+        return multipart;
+    }
+
+    private String createCommonPartXMLForItem(String shortId, String name) {
+
+        StringBuilder commonPartXML = new StringBuilder("");
+        commonPartXML.append("<ns2:citations_common xmlns:ns2=\"http://collectionspace.org/services/citation\">");
+        commonPartXML.append("    <shortIdentifier>" + shortId + "</shortIdentifier>");
+        commonPartXML.append("    <citationTermGroupList>");
+        commonPartXML.append("        <citationTermGroup>");
+        commonPartXML.append("            <termDisplayName>" + name + "</termDisplayName>");
+        commonPartXML.append("            <termName>" + name + "</termName>");
+        commonPartXML.append("            <termStatus>" + name + "</termStatus>");
+        commonPartXML.append("        </citationTermGroup>");
+        commonPartXML.append("    </citationTermGroupList>");
+        commonPartXML.append("</ns2:citations_common>");
+        return commonPartXML.toString();
+    }
+
+    @Override
+    protected PoxPayloadOut createNonExistenceInstance(String commonPartName, String identifier) {
+        String displayName = "displayName-NON_EXISTENT_ID";
+        PoxPayloadOut result = CitationAuthorityClientUtils.createCitationAuthorityInstance(
+                displayName, "nonEx", commonPartName);
+        return result;
+    }
+
+    @Override
+    protected CitationauthoritiesCommon updateInstance(CitationauthoritiesCommon citationauthoritiesCommon) {
+        CitationauthoritiesCommon result = new CitationauthoritiesCommon();
+
+        result.setDisplayName("updated-" + citationauthoritiesCommon.getDisplayName());
+        result.setVocabType("updated-" + citationauthoritiesCommon.getVocabType());
+
+        return result;
+    }
+
+    @Override
+    protected void compareUpdatedInstances(CitationauthoritiesCommon original,
+            CitationauthoritiesCommon updated) throws Exception {
+        Assert.assertEquals(updated.getDisplayName(),
+                original.getDisplayName(),
+                "Display name in updated object did not match submitted data.");
+    }
+
+    @Override
+    protected void compareReadInstances(CitationauthoritiesCommon original,
+            CitationauthoritiesCommon fromRead) throws Exception {
+        Assert.assertNotNull(fromRead.getDisplayName());
+        Assert.assertNotNull(fromRead.getShortIdentifier());
+        Assert.assertNotNull(fromRead.getRefName());
+    }
+
+    @Override
+    protected CitationsCommon updateItemInstance(CitationsCommon citationsCommon) {
+        CitationsCommon result = citationsCommon;
+        CitationTermGroupList termList = citationsCommon.getCitationTermGroupList();
+        Assert.assertNotNull(termList);
+        List<CitationTermGroup> terms = termList.getCitationTermGroup();
+        Assert.assertNotNull(terms);
+        Assert.assertTrue(terms.size() > 0);
+        terms.get(0).setTermDisplayName("updated-" + terms.get(0).getTermDisplayName());
+        terms.get(0).setTermName("updated-" + terms.get(0).getTermName());
+        terms.get(0).setTermStatus("updated-" + terms.get(0).getTermStatus());
+        result.setCitationTermGroupList(termList);
+        return result;
+    }
+
+    @Override
+    protected void compareUpdatedItemInstances(CitationsCommon original,
+            CitationsCommon updated) throws Exception {
+        CitationTermGroupList originalTermList = original.getCitationTermGroupList();
+        Assert.assertNotNull(originalTermList);
+        List<CitationTermGroup> originalTerms = originalTermList.getCitationTermGroup();
+        Assert.assertNotNull(originalTerms);
+        Assert.assertTrue(originalTerms.size() > 0);
+
+        CitationTermGroupList updatedTermList = updated.getCitationTermGroupList();
+        Assert.assertNotNull(updatedTermList);
+        List<CitationTermGroup> updatedTerms = updatedTermList.getCitationTermGroup();
+        Assert.assertNotNull(updatedTerms);
+        Assert.assertTrue(updatedTerms.size() > 0);
+
+        Assert.assertEquals(updatedTerms.get(0).getTermDisplayName(),
+                originalTerms.get(0).getTermDisplayName(),
+                "Value in updated record did not match submitted data.");
+        Assert.assertEquals(updatedTerms.get(0).getTermStatus(),
+                originalTerms.get(0).getTermDisplayName(),
+                "Value in updated record did not match submitted data.");
+    }
+
+    @Override
+    protected void verifyReadItemInstance(CitationsCommon item)
+            throws Exception {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    protected PoxPayloadOut createNonExistenceItemInstance(
+            String commonPartName, String identifier) {
+
+        String commonPartXML = createCommonPartXMLForItem("nonExShortId", "nonExItem");
+
+        try {
+            PoxPayloadOut result =
+                    CitationAuthorityClientUtils.createCitationInstance(
+                    commonPartXML, commonPartName);
+            return result;
+        } catch (DocumentException de) {
+            logger.error("Problem creating item from XML: " + de.getLocalizedMessage());
+            logger.debug("commonPartXML: " + commonPartXML);
+        }
+        return null;
+    }
+}