]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-451 Finished up the functionality to support VocabularyItem sub-resource of...
authorPatrick Schmitz <pschmitz@berkeley.edu>
Tue, 20 Oct 2009 05:32:04 +0000 (05:32 +0000)
committerPatrick Schmitz <pschmitz@berkeley.edu>
Tue, 20 Oct 2009 05:32:04 +0000 (05:32 +0000)
Renamed the vocabularyitem schemas and related classes to consistently use all-lower letters to prevent problems with the repository layer.

18 files changed:
services/client/src/main/java/org/collectionspace/services/client/BaseServiceClient.java
services/client/src/main/java/org/collectionspace/services/client/test/AbstractServiceTest.java
services/common/src/main/config/tenant-bindings.xml
services/common/src/main/java/org/collectionspace/services/common/AbstractCollectionSpaceResource.java
services/common/src/main/java/org/collectionspace/services/common/CollectionSpaceResource.java
services/common/src/main/java/org/collectionspace/services/common/context/AbstractServiceContext.java
services/common/src/main/java/org/collectionspace/services/common/context/ServiceContext.java
services/vocabulary/3rdparty/nuxeo-platform-cs-vocabulary/src/main/resources/OSGI-INF/core-types-contrib.xml
services/vocabulary/3rdparty/nuxeo-platform-cs-vocabulary/src/main/resources/OSGI-INF/ecm-types-contrib.xml
services/vocabulary/client/src/main/java/org/collectionspace/services/client/VocabularyClient.java
services/vocabulary/client/src/main/java/org/collectionspace/services/client/VocabularyProxy.java
services/vocabulary/client/src/test/java/org/collectionspace/services/client/test/VocabularyServiceTest.java
services/vocabulary/jaxb/src/main/resources/vocabularyitem_common.xsd [new file with mode: 0644]
services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/VocabularyResource.java
services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/nuxeo/VocabularyHandlerFactory.java
services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/nuxeo/VocabularyItemConstants.java [new file with mode: 0644]
services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/nuxeo/VocabularyItemDocumentModelHandler.java [new file with mode: 0644]
services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/nuxeo/VocabularyItemHandlerFactory.java [new file with mode: 0644]

index b7ca56bead7bfbff6e8f155e6e0b59cee98a03d9..9756c1a9c14b23a7268b88517496a2400416c3d8 100644 (file)
@@ -44,7 +44,11 @@ public abstract class BaseServiceClient implements CollectionSpaceClient {
     private HttpClient httpClient;\r
 \r
        public String getCommonPartName() {\r
-               return getServicePathComponent()\r
+               return getCommonPartName(getServicePathComponent());\r
+       }\r
+\r
+       public String getCommonPartName(String servicePathComponent) {\r
+               return servicePathComponent\r
                + ServiceContext.PART_LABEL_SEPERATOR\r
                + ServiceContext.PART_COMMON_LABEL;\r
        }\r
index 98ba2f35c19169f8dfc8013a867b2c2a3dfde2d9..b8faae103cc591388d16487c44be75e9ce3fdb58 100644 (file)
@@ -53,7 +53,7 @@ public abstract class AbstractServiceTest implements ServiceTest {
 
     final Logger logger = LoggerFactory.getLogger(AbstractServiceTest.class);
     // A base-level client, used (only) to obtain the base service URL.
-    private static final TestServiceClient serviceClient = new TestServiceClient();
+    protected static final TestServiceClient serviceClient = new TestServiceClient();
     // A resource identifier believed to be non-existent in actual use,
     // used when testing service calls that reference non-existent resources.
     protected final String NON_EXISTENT_ID = createNonExistentIdentifier();
@@ -88,7 +88,11 @@ public abstract class AbstractServiceTest implements ServiceTest {
     }
 
     protected void setupCreate() {
-        clearSetup("Create");
+       setupCreate("Create");
+    }
+    
+    protected void setupCreate(String label) {
+        clearSetup(label);
         // Expected status code: 201 Created
         EXPECTED_STATUS_CODE = Response.Status.CREATED.getStatusCode();
         // Type of service request being tested
@@ -104,7 +108,11 @@ public abstract class AbstractServiceTest implements ServiceTest {
     public abstract void createWithEmptyEntityBody();
 
     protected void setupCreateWithEmptyEntityBody() {
-        clearSetup("CreateWithEmptyEntityBody");
+       setupCreateWithEmptyEntityBody("CreateWithEmptyEntityBody");
+    }
+    
+    protected void setupCreateWithEmptyEntityBody(String label) {
+        clearSetup(label);
         EXPECTED_STATUS_CODE = Response.Status.BAD_REQUEST.getStatusCode();
         REQUEST_TYPE = ServiceRequestType.CREATE;
     }
@@ -113,7 +121,11 @@ public abstract class AbstractServiceTest implements ServiceTest {
     public abstract void createWithMalformedXml();
 
     protected void setupCreateWithMalformedXml() {
-        clearSetup("CreateWithMalformedXml");
+       setupCreateWithMalformedXml("CreateWithMalformedXml");
+    }
+    
+    protected void setupCreateWithMalformedXml(String label) {
+        clearSetup(label);
         // Expected status code: 400 Bad Request
         EXPECTED_STATUS_CODE = Response.Status.BAD_REQUEST.getStatusCode();
         REQUEST_TYPE = ServiceRequestType.CREATE;
@@ -123,7 +135,11 @@ public abstract class AbstractServiceTest implements ServiceTest {
     public abstract void createWithWrongXmlSchema();
 
     protected void setupCreateWithWrongXmlSchema() {
-        clearSetup("CreateWithWrongXmlSchema");
+       setupCreateWithWrongXmlSchema("CreateWithWrongXmlSchema");
+    }
+    
+    protected void setupCreateWithWrongXmlSchema(String label) {
+        clearSetup(label);
         // Expected status code: 400 Bad Request
         EXPECTED_STATUS_CODE = Response.Status.BAD_REQUEST.getStatusCode();
         REQUEST_TYPE = ServiceRequestType.CREATE;
@@ -137,7 +153,11 @@ public abstract class AbstractServiceTest implements ServiceTest {
     public abstract void read();
 
     protected void setupRead() {
-        clearSetup("Read");
+       setupRead("Read");
+    }
+    
+    protected void setupRead(String label) {
+        clearSetup(label);
         // Expected status code: 200 OK
         EXPECTED_STATUS_CODE = Response.Status.OK.getStatusCode();
         REQUEST_TYPE = ServiceRequestType.READ;
@@ -148,7 +168,10 @@ public abstract class AbstractServiceTest implements ServiceTest {
     public abstract void readNonExistent();
 
     protected void setupReadNonExistent() {
-        clearSetup("ReadNonExistent");
+       setupReadNonExistent("ReadNonExistent");
+    }
+    protected void setupReadNonExistent(String label) {
+        clearSetup(label);
         // Expected status code: 404 Not Found
         EXPECTED_STATUS_CODE = Response.Status.NOT_FOUND.getStatusCode();
         REQUEST_TYPE = ServiceRequestType.READ;
@@ -162,7 +185,11 @@ public abstract class AbstractServiceTest implements ServiceTest {
     public abstract void readList();
 
     protected void setupReadList() {
-        clearSetup("ReadList");
+       setupReadList("ReadList");
+    }
+    
+    protected void setupReadList(String label) {
+        clearSetup(label);
         // Expected status code: 200 OK
         EXPECTED_STATUS_CODE = Response.Status.OK.getStatusCode();
         REQUEST_TYPE = ServiceRequestType.READ_LIST;
@@ -179,7 +206,11 @@ public abstract class AbstractServiceTest implements ServiceTest {
     public abstract void update();
 
     protected void setupUpdate() {
-        clearSetup("Update");
+       setupUpdate("Update");
+    }
+    
+    protected void setupUpdate(String label) {
+        clearSetup(label);
         // Expected status code: 200 OK
         EXPECTED_STATUS_CODE = Response.Status.OK.getStatusCode();
         REQUEST_TYPE = ServiceRequestType.UPDATE;
@@ -190,7 +221,11 @@ public abstract class AbstractServiceTest implements ServiceTest {
     public abstract void updateWithEmptyEntityBody();
 
     protected void setupUpdateWithEmptyEntityBody() {
-        clearSetup("UpdateWithEmptyEntityBody");
+       setupUpdateWithEmptyEntityBody("UpdateWithEmptyEntityBody");
+    }
+    
+    protected void setupUpdateWithEmptyEntityBody(String label) {
+        clearSetup(label);
         EXPECTED_STATUS_CODE = Response.Status.BAD_REQUEST.getStatusCode();
         REQUEST_TYPE = ServiceRequestType.UPDATE;
     }
@@ -199,7 +234,11 @@ public abstract class AbstractServiceTest implements ServiceTest {
     public abstract void updateWithMalformedXml();
 
     protected void setupUpdateWithMalformedXml() {
-        clearSetup("UpdateWithMalformedXml");
+       setupUpdateWithMalformedXml("UpdateWithMalformedXml");
+    }
+    
+    protected void setupUpdateWithMalformedXml(String label) {
+        clearSetup(label);
         // Expected status code: 400 Bad Request
         EXPECTED_STATUS_CODE = Response.Status.BAD_REQUEST.getStatusCode();
         REQUEST_TYPE = ServiceRequestType.UPDATE;
@@ -209,7 +248,11 @@ public abstract class AbstractServiceTest implements ServiceTest {
     public abstract void updateWithWrongXmlSchema();
 
     protected void setupUpdateWithWrongXmlSchema() {
-        clearSetup("UpdateWithWrongXmlSchema");
+       setupUpdateWithWrongXmlSchema("UpdateWithWrongXmlSchema");
+    }
+    
+    protected void setupUpdateWithWrongXmlSchema(String label) {
+        clearSetup(label);
         // Expected status code: 400 Bad Request
         EXPECTED_STATUS_CODE = Response.Status.BAD_REQUEST.getStatusCode();
         REQUEST_TYPE = ServiceRequestType.UPDATE;
@@ -219,7 +262,11 @@ public abstract class AbstractServiceTest implements ServiceTest {
     public abstract void updateNonExistent();
 
     protected void setupUpdateNonExistent() {
-        clearSetup("UpdateNonExistent");
+       setupUpdateNonExistent("UpdateNonExistent");
+    }
+    
+    protected void setupUpdateNonExistent(String label) {
+        clearSetup(label);
         // Expected status code: 404 Not Found
         EXPECTED_STATUS_CODE = Response.Status.NOT_FOUND.getStatusCode();
         REQUEST_TYPE = ServiceRequestType.UPDATE;
@@ -233,7 +280,11 @@ public abstract class AbstractServiceTest implements ServiceTest {
     public abstract void delete();
 
     protected void setupDelete() {
-        clearSetup("Delete");
+       setupDelete("Delete");
+    }
+    
+    protected void setupDelete(String label) {
+        clearSetup(label);
         // Expected status code: 200 OK
         EXPECTED_STATUS_CODE = Response.Status.OK.getStatusCode();
         REQUEST_TYPE = ServiceRequestType.DELETE;
@@ -244,7 +295,11 @@ public abstract class AbstractServiceTest implements ServiceTest {
     public abstract void deleteNonExistent();
 
     protected void setupDeleteNonExistent() {
-        clearSetup("DeleteNonExistent");
+       setupDeleteNonExistent("DeleteNonExistent");
+    }
+    
+    protected void setupDeleteNonExistent(String label) {
+        clearSetup(label);
         // Expected status code: 404 Not Found
         EXPECTED_STATUS_CODE = Response.Status.NOT_FOUND.getStatusCode();
         REQUEST_TYPE = ServiceRequestType.DELETE;
index 05e8caf716b60dfbcb76ede3abf9167efac52eb9..e452193c72c65ef1ab270d714c24381f2000c5d7 100644 (file)
                 </service:part>
             </service:object>
         </tenant:serviceBindings>
+        <!-- end vocabulary service meta-data -->
+                               <!-- begin vocabularyitem service meta-data.
+                                               Note there is no Vocabularyitem service, but there is a
+                                               Repository workspace so we have to configure that. -->
+        <tenant:serviceBindings name="Vocabularyitems" version="0.1">
+            <service:repositoryClient xmlns:service='http://collectionspace.org/services/common/service'>nuxeo-java</service:repositoryClient>
+            <service:object id="1" name="Vocabularyitem" version="0.1"
+            xmlns:service='http://collectionspace.org/services/common/service'>
+                <service:part id="0" control_group="Managed"
+                            versionable="true" auditable="false"
+                            label="vocabularyitems-system" updated="" order="0">
+                    <service:content contentType="application/xml">
+                        <service:xmlContent
+                        namespaceURI="http://collectionspace.org/services/common/system"
+                        schemaLocation="http://collectionspace.org/services/common/system http://collectionspace.org/services/common/system/system-response.xsd">
+                        </service:xmlContent>
+                    </service:content>
+                </service:part>
+                <service:part id="1" control_group="Managed"
+                            versionable="true" auditable="false"
+                            label="vocabularyitems_common" updated="" order="1">
+                    <service:content contentType="application/xml">
+                        <service:xmlContent
+                        namespaceURI="http://collectionspace.org/services/vocabulary"
+                        schemaLocation="http://collectionspace.org/services/vocabulary http://services.collectionspace.org/vocabulary/vocabularyitems_common.xsd">
+                        </service:xmlContent>
+                    </service:content>
+                </service:part>
+            </service:object>
+        </tenant:serviceBindings>
         <!-- end vocabulary service meta-data -->
                 <!-- begin acquisition service meta-data -->
         <tenant:serviceBindings name="Acquisitions" version="0.1">
index e66ea566dfc4a7f383dc6450ea6ca8fec71f7365..bac653c5f6976df87def9958d6b6de52c9b4305b 100644 (file)
@@ -61,7 +61,12 @@ public abstract class AbstractCollectionSpaceResource
 \r
     @Override\r
     public RemoteServiceContext createServiceContext(MultipartInput input) throws Exception {\r
-        RemoteServiceContext ctx = new RemoteServiceContextImpl(getServiceName());\r
+        return createServiceContext(input,getServiceName());\r
+    }\r
+\r
+    @Override\r
+    public RemoteServiceContext createServiceContext(MultipartInput input, String serviceName) throws Exception {\r
+        RemoteServiceContext ctx = new RemoteServiceContextImpl(serviceName);\r
         ctx.setInput(input);\r
         return ctx;\r
     }\r
index 11062548f09d3b1ee228110299445e311a11b935..1375dd72b4ea88d7d6726f57c1a9ae1803d27c87 100644 (file)
@@ -55,13 +55,23 @@ public interface CollectionSpaceResource {
     public RepositoryClient getRepositoryClient(ServiceContext ctx);
 
     /**
-     * createServiceContext is a facotry method to create a service context
-     * a service contex is created on every service request call
+     * createServiceContext is a factory method to create a service context
+     * a service context is created on every service request call
+     * This form uses the serviceName as the default context
      * @param input
      * @return
      */
     public RemoteServiceContext createServiceContext(MultipartInput input) throws Exception;
 
+    /**
+     * createServiceContext is a factory method to create a service context
+     * a service context is created on every service request call
+     * @param input
+     * @param serviceName which service/repository context to use
+     * @return
+     */
+    public RemoteServiceContext createServiceContext(MultipartInput input, String serviceName) throws Exception;
+
     /**
      * createDocumentHandler creates a document handler and populates it with given
      * service context. document handler should never be used
index 333a5502b2e3469350c758516e36083faa6576ad..aeea00ff358b902791137e5ec4bd179f1bc03a0b 100644 (file)
@@ -82,7 +82,15 @@ public abstract class AbstractServiceContext<T1, T2>
      */
     @Override
     public String getCommonPartLabel() {
-        return getServiceName().toLowerCase() + PART_LABEL_SEPERATOR + PART_COMMON_LABEL;
+        return getCommonPartLabel(getServiceName());
+    }
+
+    /**
+     * getCommonPartLabel get common part label
+     * @return
+     */
+    public String getCommonPartLabel(String schemaName) {
+        return schemaName.toLowerCase() + PART_LABEL_SEPERATOR + PART_COMMON_LABEL;
     }
 
     @Override
index f3587cc57213187acb9a4296994cbc7c982e8387..c24c261e6d974b672c41507dc3e56ba56b708a91 100644 (file)
@@ -143,10 +143,17 @@ public interface ServiceContext<T1, T2> {
     public Map<String, ObjectPartType> getPartsMetadata();
 
     /**
-     * getCommonPartLabel retruns label for common part of a service 
+     * getCommonPartLabel returns label for common part of a service 
      * @return label
      */
     public String getCommonPartLabel();
+
+    /**
+     * getCommonPartLabel returns label for common part of a specified schema.
+     * This is useful for sub-resources. 
+     * @return label
+     */
+    public String getCommonPartLabel(String schemaName);
 }
 
 
index fd3f4448b780f02c9acdcff67840014619bf8b41..16e331cc8cb93f5907c530114c68471c7415d2a4 100644 (file)
@@ -14,7 +14,7 @@
     </doctype>
   </extension>
   <extension target="org.nuxeo.ecm.core.schema.TypeService" point="doctype">
-    <doctype name="VocabularyItem" extends="Document">
+    <doctype name="Vocabularyitem" extends="Document">
       <schema name="common"/>
       <schema name="dublincore"/>
       <schema name="vocabularyitems_common"/>
index 2d36a8f18bb8ff7b54e1afb0e41e660c04c11057..754987a801871421723e5174eda59f06ca6ee536 100644 (file)
@@ -26,7 +26,7 @@
 
   </extension>
   <extension target="org.nuxeo.ecm.platform.types.TypeService" point="types">
-    <type id="VocabularyItem" coretype="VocabularyItem">
+    <type id="Vocabularyitem" coretype="Vocabularyitem">
       <label>org.collectionspace.vocabularyitem</label>
       <!--icon>/icons/file.gif</icon-->
       <default-view>view_documents</default-view>
 
     <type id="Folder" coretype="Folder">
       <subtypes>
-        <type>VocabularyItem</type>
+        <type>Vocabularyitem</type>
       </subtypes>
     </type>
     
     <type id="Workspace" coretype="Workspace">
       <subtypes>
-        <type>VocabularyItem</type>
+        <type>Vocabularyitem</type>
       </subtypes>
     </type>
 
index fd8692412f608085504ffac6d418fe27eb1b7448..bd45a7ffdcda04c80dc75653314538314ae11f81 100644 (file)
@@ -2,12 +2,11 @@ package org.collectionspace.services.client;
 
 import javax.ws.rs.core.Response;
 
-import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.vocabulary.VocabulariesCommonList;
-
+import org.collectionspace.services.vocabulary.VocabularyitemsCommonList;
+import org.jboss.resteasy.client.ClientResponse;
 import org.jboss.resteasy.client.ProxyFactory;
 import org.jboss.resteasy.plugins.providers.RegisterBuiltin;
-import org.jboss.resteasy.client.ClientResponse;
 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
@@ -25,6 +24,10 @@ public class VocabularyClient extends BaseServiceClient {
        public String getServicePathComponent() {
                return "vocabularies";
        }
+       
+       public String getItemCommonPartName() {
+               return getCommonPartName("vocabularyitems");
+       }
 
     /**
      *
@@ -57,7 +60,7 @@ public class VocabularyClient extends BaseServiceClient {
 
     /**
      * @return
-     * @see org.collectionspace.hello.client.VocabularyProxy#getVocabulary()
+     * @see org.collectionspace.services.client.VocabularyProxy#readList()
      */
     public ClientResponse<VocabulariesCommonList> readList() {
         return vocabularyProxy.readList();
@@ -66,7 +69,7 @@ public class VocabularyClient extends BaseServiceClient {
     /**
      * @param csid
      * @return
-     * @see org.collectionspace.hello.client.VocabularyProxy#getVocabulary(java.lang.String)
+     * @see org.collectionspace.services.client.VocabularyProxy#read(java.lang.String)
      */
 
     public ClientResponse<MultipartInput> read(String csid) {
@@ -76,7 +79,7 @@ public class VocabularyClient extends BaseServiceClient {
     /**
      * @param vocabulary
      * @return
-     * @see org.collectionspace.hello.client.VocabularyProxy#createVocabulary(org.collectionspace.hello.Vocabulary)
+     * @see org.collectionspace.services.client.VocabularyProxy#createVocabulary(org.collectionspace.hello.Vocabulary)
      */
     public ClientResponse<Response> create(MultipartOutput multipart) {
         return vocabularyProxy.create(multipart);
@@ -86,7 +89,7 @@ public class VocabularyClient extends BaseServiceClient {
      * @param csid
      * @param vocabulary
      * @return
-     * @see org.collectionspace.hello.client.VocabularyProxy#updateVocabulary(java.lang.Long, org.collectionspace.hello.Vocabulary)
+     * @see org.collectionspace.services.client.VocabularyProxy#updateVocabulary(java.lang.Long, org.collectionspace.hello.Vocabulary)
      */
     public ClientResponse<MultipartInput> update(String csid, MultipartOutput multipart) {
         return vocabularyProxy.update(csid, multipart);
@@ -96,9 +99,56 @@ public class VocabularyClient extends BaseServiceClient {
     /**
      * @param csid
      * @return
-     * @see org.collectionspace.hello.client.VocabularyProxy#deleteVocabulary(java.lang.Long)
+     * @see org.collectionspace.services.client.VocabularyProxy#deleteVocabulary(java.lang.Long)
      */
     public ClientResponse<Response> delete(String csid) {
         return vocabularyProxy.delete(csid);
     }
+
+    /**
+     * @return
+     * @see org.collectionspace.services.client.VocabularyProxy#readItemList()
+     */
+    public ClientResponse<VocabularyitemsCommonList> readItemList(String vcsid) {
+        return vocabularyProxy.readItemList(vcsid);
+    }
+
+    /**
+     * @param csid
+     * @return
+     * @see org.collectionspace.services.client.VocabularyProxy#read(java.lang.String)
+     */
+
+    public ClientResponse<MultipartInput> readItem(String vcsid, String csid) {
+        return vocabularyProxy.readItem(vcsid, csid);
+    }
+
+    /**
+     * @param vocabulary
+     * @return
+     * @see org.collectionspace.services.client.VocabularyProxy#createVocabulary(org.collectionspace.hello.Vocabulary)
+     */
+    public ClientResponse<Response> createItem(String vcsid, MultipartOutput multipart) {
+        return vocabularyProxy.createItem(vcsid, multipart);
+    }
+
+    /**
+     * @param csid
+     * @param vocabulary
+     * @return
+     * @see org.collectionspace.services.client.VocabularyProxy#updateVocabulary(java.lang.Long, org.collectionspace.hello.Vocabulary)
+     */
+    public ClientResponse<MultipartInput> updateItem(String vcsid, String csid, MultipartOutput multipart) {
+        return vocabularyProxy.updateItem(vcsid, csid, multipart);
+
+    }
+
+    /**
+     * @param csid
+     * @return
+     * @see org.collectionspace.services.client.VocabularyProxy#deleteVocabulary(java.lang.Long)
+     */
+    public ClientResponse<Response> deleteItem(String vcsid, String csid) {
+        return vocabularyProxy.deleteItem(vcsid, csid);
+    }
 }
index 4b293363aa7024ffe75944cc91fecba030ba7b67..066e1f7cbbe913a3c5073d1e7f21266d7d664a1b 100644 (file)
@@ -11,6 +11,7 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.core.Response;
 
 import org.collectionspace.services.vocabulary.VocabulariesCommonList;
+import org.collectionspace.services.vocabulary.VocabularyitemsCommonList;
 import org.jboss.resteasy.client.ClientResponse;
 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
@@ -23,6 +24,7 @@ import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
 @Consumes({"multipart/mixed"})
 public interface VocabularyProxy {
 
+    // List Vocabularies
     @GET
     @Produces({"application/xml"})
     ClientResponse<VocabulariesCommonList> readList();
@@ -45,4 +47,30 @@ public interface VocabularyProxy {
     @DELETE
     @Path("/{csid}")
     ClientResponse<Response> delete(@PathParam("csid") String csid);
+
+    // List Items
+    @GET
+    @Produces({"application/xml"})
+    @Path("/{vcsid}/items/")
+    ClientResponse<VocabularyitemsCommonList> readItemList(@PathParam("vcsid") String vcsid);
+
+    //(C)reate Item
+    @POST
+    @Path("/{vcsid}/items/")
+    ClientResponse<Response> createItem(@PathParam("vcsid") String vcsid, MultipartOutput multipart);
+
+    //(R)ead
+    @GET
+    @Path("/{vcsid}/items/{csid}")
+    ClientResponse<MultipartInput> readItem(@PathParam("vcsid") String vcsid, @PathParam("csid") String csid);
+
+    //(U)pdate
+    @PUT
+    @Path("/{vcsid}/items/{csid}")
+    ClientResponse<MultipartInput> updateItem(@PathParam("vcsid") String vcsid, @PathParam("csid") String csid, MultipartOutput multipart);
+
+    //(D)elete
+    @DELETE
+    @Path("/{vcsid}/items/{csid}")
+    ClientResponse<Response> deleteItem(@PathParam("vcsid") String vcsid, @PathParam("csid") String csid);
 }
index cf74fed98ae9cb312d13fca080bbd1a51f26f58c..b7c584bfafb2e06be345aef28e863b918a0bbd5e 100644 (file)
 package org.collectionspace.services.client.test;
 
 import java.util.List;
+
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
 import org.collectionspace.services.client.VocabularyClient;
 import org.collectionspace.services.vocabulary.VocabulariesCommon;
 import org.collectionspace.services.vocabulary.VocabulariesCommonList;
-
+import org.collectionspace.services.vocabulary.VocabularyitemsCommon;
+import org.collectionspace.services.vocabulary.VocabularyitemsCommonList;
 import org.jboss.resteasy.client.ClientResponse;
-
 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
 import org.jboss.resteasy.plugins.providers.multipart.OutputPart;
@@ -50,7 +51,9 @@ public class VocabularyServiceTest extends AbstractServiceTest {
     // Instance variables specific to this test.
     private VocabularyClient client = new VocabularyClient();
     final String SERVICE_PATH_COMPONENT = "vocabularies";
+    final String ITEM_SERVICE_PATH_COMPONENT = "items";
     private String knownResourceId = null;
+    private String knownItemResourceId = null;
 
     // ---------------------------------------------------------------
     // CRUD tests : CREATE tests
@@ -89,12 +92,48 @@ public class VocabularyServiceTest extends AbstractServiceTest {
         knownResourceId = extractId(res);
         verbose("create: knownResourceId=" + knownResourceId);
     }
+    
+    @Test(dependsOnMethods = {"create"})
+    public void createItem() {
+        setupCreate("Create Item");
+
+        knownItemResourceId = createItemInVocab(knownResourceId);
+        verbose("createItem: knownItemResourceId=" + knownItemResourceId);
+    }
+    
+    private String createItemInVocab(String vcsid) {
+        // Submit the request to the service and store the response.
+        String identifier = createIdentifier();
+
+        verbose("createItem:...");
+        MultipartOutput multipart = createVocabularyItemInstance(vcsid, identifier);
+        ClientResponse<Response> res = client.createItem(vcsid, multipart);
+
+        int statusCode = res.getStatus();
+
+        // Check the status code of the response: does it match
+        // the expected response(s)?
+        //
+        // Specifically:
+        // Does it fall within the set of valid status codes?
+        // Does it exactly match the expected status code?
+        verbose("createItem: status = " + statusCode);
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+
+        return extractId(res);
+    }
 
     @Override
-    @Test(dependsOnMethods = {"create"})
+    @Test(dependsOnMethods = {"create", "createItem"})
     public void createList() {
         for(int i = 0; i < 3; i++){
             create();
+            // Add 3 items to each vocab
+            for(int j = 0; j < 3; j++){
+               createItem();
+            }
         }
     }
 
@@ -176,7 +215,7 @@ public class VocabularyServiceTest extends AbstractServiceTest {
     invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
     Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
     }
-     */
+    */
     // ---------------------------------------------------------------
     // CRUD tests : READ tests
     // ---------------------------------------------------------------
@@ -209,6 +248,33 @@ public class VocabularyServiceTest extends AbstractServiceTest {
         }
     }
 
+    @Test(dependsOnMethods = {"createItem", "read"})
+    public void readItem() {
+
+        // Perform setup.
+        setupRead("Read Item");
+
+        // Submit the request to the service and store the response.
+        ClientResponse<MultipartInput> res = client.readItem(knownResourceId, knownItemResourceId);
+        int statusCode = res.getStatus();
+
+        // Check the status code of the response: does it match
+        // the expected response(s)?
+        verbose("readItem: status = " + statusCode);
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+        //FIXME: remove the following try catch once Aron fixes signatures
+        try{
+            MultipartInput input = (MultipartInput) res.getEntity();
+            VocabularyitemsCommon vocabularyItem = (VocabularyitemsCommon) extractPart(input,
+                       client.getItemCommonPartName(), VocabularyitemsCommon.class);
+            Assert.assertNotNull(vocabularyItem);
+        }catch(Exception e){
+            throw new RuntimeException(e);
+        }
+    }
+
     // Failure outcomes
     @Override
     @Test(dependsOnMethods = {"read"})
@@ -229,6 +295,23 @@ public class VocabularyServiceTest extends AbstractServiceTest {
         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
     }
 
+    @Test(dependsOnMethods = {"readItem", "readNonExistent"})
+    public void readItemNonExistent() {
+
+        // Perform setup.
+        setupReadNonExistent("Read Non-Existent Item");
+
+        // Submit the request to the service and store the response.
+        ClientResponse<MultipartInput> res = client.readItem(knownResourceId, NON_EXISTENT_ID);
+        int statusCode = res.getStatus();
+
+        // Check the status code of the response: does it match
+        // the expected response(s)?
+        verbose("readItemNonExistent: status = " + res.getStatus());
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+    }
     // ---------------------------------------------------------------
     // CRUD tests : READ_LIST tests
     // ---------------------------------------------------------------
@@ -259,16 +342,57 @@ public class VocabularyServiceTest extends AbstractServiceTest {
                     list.getVocabularyListItem();
             int i = 0;
             for(VocabulariesCommonList.VocabularyListItem item : items){
+               String csid = item.getCsid();
                 verbose("readList: list-item[" + i + "] csid=" +
-                        item.getCsid());
+                        csid);
                 verbose("readList: list-item[" + i + "] displayName=" +
                         item.getDisplayName());
                 verbose("readList: list-item[" + i + "] URI=" +
                         item.getUri());
+                readItemList(csid);
                 i++;
             }
         }
+    }
+    
+    @Test(dependsOnMethods = {"readItem"})
+    public void readItemList() {
+       readItemList(knownResourceId);
+    }
+
+    private void readItemList(String vcsid) {
+        // Perform setup.
+        setupReadList("Read Item List");
+
+        // Submit the request to the service and store the response.
+        ClientResponse<VocabularyitemsCommonList> res = 
+               client.readItemList(vcsid);
+        VocabularyitemsCommonList list = res.getEntity();
+        int statusCode = res.getStatus();
+
+        // Check the status code of the response: does it match
+        // the expected response(s)?
+        verbose("  readItemList: status = " + res.getStatus());
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
 
+        // Optionally output additional data about list members for debugging.
+        boolean iterateThroughList = false;
+        if(iterateThroughList && logger.isDebugEnabled()){
+            List<VocabularyitemsCommonList.VocabularyitemListItem> items =
+                    list.getVocabularyitemListItem();
+            int i = 0;
+            for(VocabularyitemsCommonList.VocabularyitemListItem item : items){
+                verbose("  readItemList: list-item[" + i + "] csid=" +
+                        item.getCsid());
+                verbose("  readItemList: list-item[" + i + "] displayName=" +
+                        item.getDisplayName());
+                verbose("  readItemList: list-item[" + i + "] URI=" +
+                        item.getUri());
+                i++;
+            }
+        }
     }
 
     // Failure outcomes
@@ -291,7 +415,7 @@ public class VocabularyServiceTest extends AbstractServiceTest {
             verbose("update: read status = " + res.getStatus());
             Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE);
 
-            verbose("got object to update with ID: " + knownResourceId);
+            verbose("got Vocabulary to update with ID: " + knownResourceId);
             MultipartInput input = (MultipartInput) res.getEntity();
             VocabulariesCommon vocabulary = (VocabulariesCommon) extractPart(input,
                        client.getCommonPartName(), VocabulariesCommon.class);
@@ -299,8 +423,8 @@ public class VocabularyServiceTest extends AbstractServiceTest {
 
             // Update the content of this resource.
             vocabulary.setDisplayName("updated-" + vocabulary.getDisplayName());
-             vocabulary.setVocabType("updated-" + vocabulary.getVocabType());
-           verbose("to be updated object", vocabulary, VocabulariesCommon.class);
+            vocabulary.setVocabType("updated-" + vocabulary.getVocabType());
+            verbose("to be updated Vocabulary", vocabulary, VocabulariesCommon.class);
             // Submit the request to the service and store the response.
             MultipartOutput output = new MultipartOutput();
             OutputPart commonPart = output.addPart(vocabulary, MediaType.APPLICATION_XML_TYPE);
@@ -329,6 +453,57 @@ public class VocabularyServiceTest extends AbstractServiceTest {
         }
     }
 
+    @Test(dependsOnMethods = {"readItem", "update"})
+    public void updateItem() {
+
+        // Perform setup.
+        setupUpdate("Update Item");
+
+        try{ //ideally, just remove try-catch and let the exception bubble up
+            // Retrieve an existing resource that we can update.
+            ClientResponse<MultipartInput> res =
+                    client.readItem(knownResourceId, knownItemResourceId);
+            verbose("updateItem: read status = " + res.getStatus());
+            Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE);
+
+            verbose("got VocabularyItem to update with ID: " + knownItemResourceId 
+                       + " in Vocab: " + knownResourceId );
+            MultipartInput input = (MultipartInput) res.getEntity();
+            VocabularyitemsCommon vocabularyItem = (VocabularyitemsCommon) extractPart(input,
+                       client.getItemCommonPartName(), VocabularyitemsCommon.class);
+            Assert.assertNotNull(vocabularyItem);
+
+            // Update the content of this resource.
+            vocabularyItem.setDisplayName("updated-" + vocabularyItem.getDisplayName());
+            verbose("to be updated VocabularyItem", vocabularyItem, VocabularyitemsCommon.class);
+            // Submit the request to the service and store the response.
+            MultipartOutput output = new MultipartOutput();
+            OutputPart commonPart = output.addPart(vocabularyItem, MediaType.APPLICATION_XML_TYPE);
+            commonPart.getHeaders().add("label", client.getItemCommonPartName());
+
+            res = client.updateItem(knownResourceId, knownItemResourceId, output);
+            int statusCode = res.getStatus();
+            // Check the status code of the response: does it match the expected response(s)?
+            verbose("updateItem: status = " + res.getStatus());
+            Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                    invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+            Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+
+
+            input = (MultipartInput) res.getEntity();
+            VocabularyitemsCommon updatedVocabularyItem =
+                    (VocabularyitemsCommon) extractPart(input,
+                               client.getItemCommonPartName(), VocabularyitemsCommon.class);
+            Assert.assertNotNull(updatedVocabularyItem);
+
+            Assert.assertEquals(updatedVocabularyItem.getDisplayName(),
+                       vocabularyItem.getDisplayName(),
+                    "Data in updated VocabularyItem did not match submitted data.");
+        }catch(Exception e){
+            e.printStackTrace();
+        }
+    }
+
     // Failure outcomes
     // Placeholders until the three tests below can be uncommented.
     // See Issue CSPACE-401.
@@ -408,6 +583,7 @@ public class VocabularyServiceTest extends AbstractServiceTest {
     Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
     }
      */
+
     @Override
     @Test(dependsOnMethods = {"update", "testSubmitRequest"})
     public void updateNonExistent() {
@@ -433,6 +609,30 @@ public class VocabularyServiceTest extends AbstractServiceTest {
         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
     }
 
+    @Test(dependsOnMethods = {"updateItem", "testItemSubmitRequest"})
+    public void updateNonExistentItem() {
+       
+        // Perform setup.
+        setupUpdateNonExistent("Update Non-Existent Item");
+
+        // Submit the request to the service and store the response.
+        // Note: The ID used in this 'create' call may be arbitrary.
+        // The only relevant ID may be the one used in update(), below.
+
+        // The only relevant ID may be the one used in update(), below.
+        MultipartOutput multipart = createVocabularyItemInstance(knownResourceId, NON_EXISTENT_ID);
+        ClientResponse<MultipartInput> res =
+                client.updateItem(knownResourceId, NON_EXISTENT_ID, multipart);
+        int statusCode = res.getStatus();
+
+        // Check the status code of the response: does it match
+        // the expected response(s)?
+        verbose("updateNonExistentItem: status = " + res.getStatus());
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+    }
+
     // ---------------------------------------------------------------
     // CRUD tests : DELETE tests
     // ---------------------------------------------------------------
@@ -456,6 +656,24 @@ public class VocabularyServiceTest extends AbstractServiceTest {
         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
     }
 
+    @Test(dependsOnMethods = {"createItem", "readItemList", "testItemSubmitRequest", "updateItem"})
+    public void deleteItem() {
+
+        // Perform setup.
+        setupDelete("Delete Item");
+
+        // Submit the request to the service and store the response.
+        ClientResponse<Response> res = client.deleteItem(knownResourceId, knownItemResourceId);
+        int statusCode = res.getStatus();
+
+        // Check the status code of the response: does it match
+        // the expected response(s)?
+        verbose("delete: status = " + res.getStatus());
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+    }
+
     // Failure outcomes
     @Override
     @Test(dependsOnMethods = {"delete"})
@@ -476,6 +694,24 @@ public class VocabularyServiceTest extends AbstractServiceTest {
         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
     }
 
+    @Test(dependsOnMethods = {"deleteItem"})
+    public void deleteNonExistentItem() {
+
+        // Perform setup.
+        setupDeleteNonExistent("Delete Non-Existent Item");
+
+        // Submit the request to the service and store the response.
+        ClientResponse<Response> res = client.deleteItem(knownResourceId, NON_EXISTENT_ID);
+        int statusCode = res.getStatus();
+
+        // Check the status code of the response: does it match
+        // the expected response(s)?
+        verbose("deleteNonExistent: status = " + res.getStatus());
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+    }
+
     // ---------------------------------------------------------------
     // Utility tests : tests of code used in tests above
     // ---------------------------------------------------------------
@@ -501,6 +737,24 @@ public class VocabularyServiceTest extends AbstractServiceTest {
 
     }
 
+    @Test(dependsOnMethods = {"createItem", "readItem", "testSubmitRequest"})
+    public void testItemSubmitRequest() {
+
+        // Expected status code: 200 OK
+        final int EXPECTED_STATUS_CODE = Response.Status.OK.getStatusCode();
+
+        // Submit the request to the service and store the response.
+        String method = ServiceRequestType.READ.httpMethodName();
+        String url = getItemResourceURL(knownResourceId, knownItemResourceId);
+        int statusCode = submitRequest(method, url);
+
+        // Check the status code of the response: does it match
+        // the expected response(s)?
+        verbose("testItemSubmitRequest: url=" + url + " status=" + statusCode);
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+
+    }
+
     // ---------------------------------------------------------------
     // Utility methods used by tests above
     // ---------------------------------------------------------------
@@ -509,6 +763,35 @@ public class VocabularyServiceTest extends AbstractServiceTest {
         return SERVICE_PATH_COMPONENT;
     }
 
+    public String getItemServicePathComponent() {
+        return ITEM_SERVICE_PATH_COMPONENT;
+    }
+
+    /**
+     * Returns the root URL for a service.
+     *
+     * This URL consists of a base URL for all services, followed by
+     * a path component for the owning vocabulary, followed by the 
+     * path component for the items.
+     *
+     * @return The root URL for a service.
+     */
+    protected String getItemServiceRootURL(String parentResourceIdentifier) {
+        return getResourceURL(parentResourceIdentifier)+"/"+getItemServicePathComponent();
+    }
+
+    /**
+     * Returns the URL of a specific resource managed by a service, and
+     * designated by an identifier (such as a universally unique ID, or UUID).
+     *
+     * @param  resourceIdentifier  An identifier (such as a UUID) for a resource.
+     *
+     * @return The URL of a specific resource managed by a service.
+     */
+    protected String getItemResourceURL(String parentResourceIdentifier, String resourceIdentifier) {
+        return getItemServiceRootURL(parentResourceIdentifier) + "/" + resourceIdentifier;
+    }
+
     private MultipartOutput createVocabularyInstance(String identifier) {
         return createVocabularyInstance(
                 "displayName-" + identifier,
@@ -527,4 +810,17 @@ public class VocabularyServiceTest extends AbstractServiceTest {
 
         return multipart;
     }
+
+    private MultipartOutput createVocabularyItemInstance(String inVocabulary, String displayName) {
+       VocabularyitemsCommon vocabularyItem = new VocabularyitemsCommon();
+       vocabularyItem.setInVocabulary(inVocabulary);
+       vocabularyItem.setDisplayName(displayName);
+        MultipartOutput multipart = new MultipartOutput();
+        OutputPart commonPart = multipart.addPart(vocabularyItem, MediaType.APPLICATION_XML_TYPE);
+        commonPart.getHeaders().add("label", client.getItemCommonPartName());
+
+        verbose("to be created, vocabularyitem common ", vocabularyItem, VocabularyitemsCommon.class);
+
+        return multipart;
+    }
 }
diff --git a/services/vocabulary/jaxb/src/main/resources/vocabularyitem_common.xsd b/services/vocabulary/jaxb/src/main/resources/vocabularyitem_common.xsd
new file mode 100644 (file)
index 0000000..9b62ae2
--- /dev/null
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<xs:schema 
+  xmlns:xs="http://www.w3.org/2001/XMLSchema"
+  xmlns:ns="http://collectionspace.org/services/vocabulary"
+  xmlns="http://collectionspace.org/services/vocabulary"
+  targetNamespace="http://collectionspace.org/services/vocabulary"
+  version="0.1"
+>
+
+
+<!-- avoid XmlRootElement nightnmare, see http://weblogs.java.net/blog/kohsuke/archive/2006/03/why_does_jaxb_p.html-->
+<!-- See http://wiki.collectionspace.org/display/collectionspace/Vocabulary+Schema -->    
+    
+    <!-- Vocabularyitem -->
+    <xs:element name="vocabularyitems_common">
+        <xs:complexType>
+            <xs:sequence>
+                <!--  Common identifier -->
+                <xs:element name="csid" type="xs:string" />
+                
+                <!--  Vocabularyitem Information Group -->
+                <!--  inVocabulary is the csid of the owning Vocabulary -->
+                <xs:element name="inVocabulary" type="xs:string" />
+                <xs:element name="displayName" type="xs:string"/>
+
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+    
+    <!-- Vocabularyitem instances, as in nuxeo repository -->
+    <xs:element name="vocabularyitems-common-list">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="vocabularyitem_list_item" maxOccurs="unbounded">
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:element name="displayName" type="xs:string"
+                                minOccurs="1" />
+                            <!-- uri to retrieve vocabularyitem details -->
+                            <xs:element name="uri" type="xs:anyURI"
+                                minOccurs="1" />
+                            <xs:element name="csid" type="xs:string"
+                                minOccurs="1" />
+                        </xs:sequence>
+                    </xs:complexType>
+                </xs:element>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+    
+</xs:schema>
+
index cf7b7e2768601e3ddf9d454617b3fa124ac497fa..f0ea4e94bb88b72f3d7233645d763347a1ea01ca 100644 (file)
 package org.collectionspace.services.vocabulary;
 
 import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
 import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.Response;
@@ -38,13 +38,15 @@ import javax.ws.rs.core.UriBuilder;
 import javax.ws.rs.core.UriInfo;
 
 import org.collectionspace.services.common.AbstractCollectionSpaceResource;
-import org.collectionspace.services.vocabulary.nuxeo.VocabularyHandlerFactory;
 import org.collectionspace.services.common.ClientType;
 import org.collectionspace.services.common.ServiceMain;
 import org.collectionspace.services.common.context.RemoteServiceContext;
 import org.collectionspace.services.common.context.ServiceContext;
-import org.collectionspace.services.common.repository.DocumentNotFoundException;
 import org.collectionspace.services.common.repository.DocumentHandler;
+import org.collectionspace.services.common.repository.DocumentNotFoundException;
+import org.collectionspace.services.vocabulary.nuxeo.VocabularyHandlerFactory;
+import org.collectionspace.services.vocabulary.nuxeo.VocabularyItemDocumentModelHandler;
+import org.collectionspace.services.vocabulary.nuxeo.VocabularyItemHandlerFactory;
 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
 import org.jboss.resteasy.util.HttpResponseCodes;
@@ -56,7 +58,8 @@ import org.slf4j.LoggerFactory;
 @Produces("multipart/mixed")
 public class VocabularyResource extends AbstractCollectionSpaceResource {
 
-    private final static String serviceName = "vocabularies";
+    private final static String vocabularyServiceName = "vocabularies";
+    private final static String vocabularyItemServiceName = "vocabularyitems";
     final Logger logger = LoggerFactory.getLogger(VocabularyResource.class);
     //FIXME retrieve client type from configuration
     final static ClientType CLIENT_TYPE = ServiceMain.getInstance().getClientType();
@@ -67,9 +70,21 @@ public class VocabularyResource extends AbstractCollectionSpaceResource {
 
     @Override
     public String getServiceName() {
-        return serviceName;
+        return vocabularyServiceName;
+    }
+
+    public String getItemServiceName() {
+        return vocabularyItemServiceName;
     }
 
+    /*
+    public RemoteServiceContext createItemServiceContext(MultipartInput input) throws Exception {
+        RemoteServiceContext ctx = new RemoteServiceContextImpl(getItemServiceName());
+        ctx.setInput(input);
+        return ctx;
+    }
+    */
+
     @Override
     public DocumentHandler createDocumentHandler(RemoteServiceContext ctx) throws Exception {
         DocumentHandler docHandler = VocabularyHandlerFactory.getInstance().getHandler(
@@ -84,6 +99,23 @@ public class VocabularyResource extends AbstractCollectionSpaceResource {
         return docHandler;
     }
 
+    private DocumentHandler createItemDocumentHandler(
+               RemoteServiceContext ctx,
+               String inVocabulary) throws Exception {
+        DocumentHandler docHandler = VocabularyItemHandlerFactory.getInstance().getHandler(
+                ctx.getRepositoryClientType().toString());
+        docHandler.setServiceContext(ctx);
+        ((VocabularyItemDocumentModelHandler)docHandler).setInVocabulary(inVocabulary);
+        if(ctx.getInput() != null){
+            Object obj = ctx.getInputPart(ctx.getCommonPartLabel(getItemServiceName()),
+                                                                                               VocabularyitemsCommon.class);
+            if(obj != null){
+                docHandler.setCommonPart((VocabularyitemsCommon) obj);
+            }
+        }
+        return docHandler;
+    }
+
     @POST
     public Response createVocabulary(MultipartInput input) {
         try{
@@ -240,4 +272,201 @@ public class VocabularyResource extends AbstractCollectionSpaceResource {
         }
 
     }
+
+    /*************************************************************************
+     * VocabularyItem parts - this is a sub-resource of Vocabulary
+     *************************************************************************/
+
+     @POST
+     @Path("{csid}/items")
+     public Response createVocabularyItem(@PathParam("csid") String parentcsid, MultipartInput input) {
+         try{
+             RemoteServiceContext ctx = createServiceContext(input, getItemServiceName());
+             DocumentHandler handler = createItemDocumentHandler(ctx, parentcsid);
+             String itemcsid = getRepositoryClient(ctx).create(ctx, handler);
+             UriBuilder path = UriBuilder.fromResource(VocabularyResource.class);
+             path.path(parentcsid + "/items/" + itemcsid);
+             Response response = Response.created(path.build()).build();
+             return response;
+         }catch(Exception e){
+             if(logger.isDebugEnabled()){
+                 logger.debug("Caught exception in createVocabularyItem", e);
+             }
+             Response response = Response.status(
+                     Response.Status.INTERNAL_SERVER_ERROR).entity("Create failed").type("text/plain").build();
+             throw new WebApplicationException(response);
+         }
+     }
+
+     @GET
+     @Path("{csid}/items/{itemcsid}")
+     public MultipartOutput getVocabularyItem(
+                @PathParam("csid") String parentcsid,
+             @PathParam("itemcsid") String itemcsid) {
+         if(logger.isDebugEnabled()){
+             logger.debug("getVocabularyItem with parentcsid=" 
+                        + parentcsid + " and itemcsid=" + itemcsid);
+         }
+         if(parentcsid == null || "".equals(parentcsid)){
+             logger.error("getVocabularyItem: missing csid!");
+             Response response = Response.status(Response.Status.BAD_REQUEST).entity(
+                     "get failed on VocabularyItem csid=" + parentcsid).type(
+                     "text/plain").build();
+             throw new WebApplicationException(response);
+         }
+         if(itemcsid == null || "".equals(itemcsid)){
+             logger.error("getVocabularyItem: missing itemcsid!");
+             Response response = Response.status(Response.Status.BAD_REQUEST).entity(
+                     "get failed on VocabularyItem itemcsid=" + itemcsid).type(
+                     "text/plain").build();
+             throw new WebApplicationException(response);
+         }
+         MultipartOutput result = null;
+         try{
+                // Note that we have to create the service context for the Items, not the main service 
+             RemoteServiceContext ctx = createServiceContext(null, getItemServiceName());
+             DocumentHandler handler = createItemDocumentHandler(ctx, parentcsid);
+             getRepositoryClient(ctx).get(ctx, itemcsid, handler);
+             // TODO should we assert that the item is in the passed vocab?
+             result = ctx.getOutput();
+         }catch(DocumentNotFoundException dnfe){
+             if(logger.isDebugEnabled()){
+                 logger.debug("getVocabularyItem", dnfe);
+             }
+             Response response = Response.status(Response.Status.NOT_FOUND).entity(
+                     "Get failed on VocabularyItem csid=" + itemcsid).type(
+                     "text/plain").build();
+             throw new WebApplicationException(response);
+         }catch(Exception e){
+             if(logger.isDebugEnabled()){
+                 logger.debug("getVocabularyItem", e);
+             }
+             Response response = Response.status(
+                     Response.Status.INTERNAL_SERVER_ERROR).entity("Get failed").type("text/plain").build();
+             throw new WebApplicationException(response);
+         }
+         if(result == null){
+             Response response = Response.status(Response.Status.NOT_FOUND).entity(
+                     "Get failed, the requested VocabularyItem CSID:" + itemcsid + ": was not found.").type(
+                     "text/plain").build();
+             throw new WebApplicationException(response);
+         }
+         return result;
+     }
+
+     @GET
+     @Path("{csid}/items")
+     @Produces("application/xml")
+     public VocabularyitemsCommonList getVocabularyItemList(
+                @PathParam("csid") String parentcsid,
+                @Context UriInfo ui) {
+         VocabularyitemsCommonList vocabularyItemObjectList = new VocabularyitemsCommonList();
+         try{
+                // Note that we have to create the service context for the Items, not the main service 
+             RemoteServiceContext ctx = createServiceContext(null, getItemServiceName());
+             DocumentHandler handler = createItemDocumentHandler(ctx, parentcsid);
+             // HACK This should be a search with the parentcsid. The 
+             // handler.getCommonPartList method will filter these for us, 
+             // which is really silly, but works for now.
+             getRepositoryClient(ctx).getAll(ctx, handler);
+             vocabularyItemObjectList = (VocabularyitemsCommonList) handler.getCommonPartList();
+         }catch(Exception e){
+             if(logger.isDebugEnabled()){
+                 logger.debug("Caught exception in getVocabularyItemList", e);
+             }
+             Response response = Response.status(
+                     Response.Status.INTERNAL_SERVER_ERROR).entity("Index failed").type("text/plain").build();
+             throw new WebApplicationException(response);
+         }
+         return vocabularyItemObjectList;
+     }
+
+     @PUT
+     @Path("{csid}/items/{itemcsid}")
+     public MultipartOutput updateVocabularyItem(
+                @PathParam("csid") String parentcsid,
+             @PathParam("itemcsid") String itemcsid,
+             MultipartInput theUpdate) {
+         if(logger.isDebugEnabled()){
+             logger.debug("updateVocabularyItem with parentcsid=" + parentcsid + " and itemcsid=" + itemcsid);
+         }
+         if(parentcsid == null || "".equals(parentcsid)){
+             logger.error("updateVocabularyItem: missing csid!");
+             Response response = Response.status(Response.Status.BAD_REQUEST).entity(
+                     "update failed on VocabularyItem parentcsid=" + parentcsid).type(
+                     "text/plain").build();
+             throw new WebApplicationException(response);
+         }
+         if(itemcsid == null || "".equals(itemcsid)){
+             logger.error("updateVocabularyItem: missing itemcsid!");
+             Response response = Response.status(Response.Status.BAD_REQUEST).entity(
+                     "update failed on VocabularyItem=" + itemcsid).type(
+                     "text/plain").build();
+             throw new WebApplicationException(response);
+         }
+         MultipartOutput result = null;
+         try{
+                // Note that we have to create the service context for the Items, not the main service 
+             RemoteServiceContext ctx = createServiceContext(theUpdate, getItemServiceName());
+             DocumentHandler handler = createItemDocumentHandler(ctx, parentcsid);
+             getRepositoryClient(ctx).update(ctx, itemcsid, handler);
+             result = ctx.getOutput();
+         }catch(DocumentNotFoundException dnfe){
+             if(logger.isDebugEnabled()){
+                 logger.debug("caugth exception in updateVocabularyItem", dnfe);
+             }
+             Response response = Response.status(Response.Status.NOT_FOUND).entity(
+                     "Update failed on VocabularyItem csid=" + itemcsid).type(
+                     "text/plain").build();
+             throw new WebApplicationException(response);
+         }catch(Exception e){
+             Response response = Response.status(
+                     Response.Status.INTERNAL_SERVER_ERROR).entity("Update failed").type("text/plain").build();
+             throw new WebApplicationException(response);
+         }
+         return result;
+     }
+
+     @DELETE
+     @Path("{csid}/items/{itemcsid}")
+     public Response deleteVocabularyItem(
+                @PathParam("csid") String parentcsid,
+         @PathParam("itemcsid") String itemcsid) {
+         if(logger.isDebugEnabled()){
+             logger.debug("deleteVocabularyItem with parentcsid=" + parentcsid + " and itemcsid=" + itemcsid);
+         }
+         if(parentcsid == null || "".equals(parentcsid)){
+             logger.error("deleteVocabularyItem: missing csid!");
+             Response response = Response.status(Response.Status.BAD_REQUEST).entity(
+                     "delete failed on VocabularyItem parentcsid=" + parentcsid).type(
+                     "text/plain").build();
+             throw new WebApplicationException(response);
+         }
+         if(itemcsid == null || "".equals(itemcsid)){
+             logger.error("deleteVocabularyItem: missing itemcsid!");
+             Response response = Response.status(Response.Status.BAD_REQUEST).entity(
+                     "delete failed on VocabularyItem=" + itemcsid).type(
+                     "text/plain").build();
+             throw new WebApplicationException(response);
+         }
+         try{
+                // Note that we have to create the service context for the Items, not the main service 
+             RemoteServiceContext ctx = createServiceContext(null, getItemServiceName());
+             getRepositoryClient(ctx).delete(ctx, itemcsid);
+             return Response.status(HttpResponseCodes.SC_OK).build();
+         }catch(DocumentNotFoundException dnfe){
+             if(logger.isDebugEnabled()){
+                 logger.debug("caught exception in deleteVocabulary", dnfe);
+             }
+             Response response = Response.status(Response.Status.NOT_FOUND).entity(
+                     "Delete failed on VocabularyItem itemcsid=" + itemcsid).type(
+                     "text/plain").build();
+             throw new WebApplicationException(response);
+         }catch(Exception e){
+             Response response = Response.status(
+                     Response.Status.INTERNAL_SERVER_ERROR).entity("Delete failed").type("text/plain").build();
+             throw new WebApplicationException(response);
+         }
+
+     }
 }
index 721c3008369c99a341d9764cf2857137979f66ea..709df73e54313bc6a17ab3b047c64cfa6a04783b 100644 (file)
@@ -29,7 +29,7 @@ import org.collectionspace.services.common.repository.DocumentHandlerFactory;
 
 
 /**
- * VocabularyHandlerFactory creates handlers for collectionobject based
+ * VocabularyHandlerFactory creates handlers for vocabulary based
  * on type of Nuxeo client used
  *
  * $LastChangedRevision: $
diff --git a/services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/nuxeo/VocabularyItemConstants.java b/services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/nuxeo/VocabularyItemConstants.java
new file mode 100644 (file)
index 0000000..bbedce4
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+ *  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 University of California at Berkeley
+
+ *  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.vocabulary.nuxeo;
+
+/**
+ * VocabularyConstants processes CollectionObject document
+ *
+ */
+public class VocabularyItemConstants {
+
+    public final static String NUXEO_DOCTYPE = "Vocabularyitem";
+    public final static String NUXEO_SCHEMA_NAME = "vocabularyitem";
+    public final static String NUXEO_DC_TITLE = "CollectionSpace-Vocabularyitem";
+}
diff --git a/services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/nuxeo/VocabularyItemDocumentModelHandler.java b/services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/nuxeo/VocabularyItemDocumentModelHandler.java
new file mode 100644 (file)
index 0000000..9c95560
--- /dev/null
@@ -0,0 +1,177 @@
+/**
+ *  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 University of California at Berkeley
+
+ *  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.vocabulary.nuxeo;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.collectionspace.services.VocabularyItemJAXBSchema;
+import org.collectionspace.services.common.repository.DocumentWrapper;
+import org.collectionspace.services.nuxeo.client.java.RemoteDocumentModelHandler;
+import org.collectionspace.services.vocabulary.VocabularyitemsCommon;
+import org.collectionspace.services.vocabulary.VocabularyitemsCommonList;
+import org.collectionspace.services.vocabulary.VocabularyitemsCommonList.VocabularyitemListItem;
+import org.nuxeo.ecm.core.api.DocumentModel;
+import org.nuxeo.ecm.core.api.DocumentModelList;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * VocabularyItemDocumentModelHandler
+ *
+ * $LastChangedRevision: $
+ * $LastChangedDate: $
+ */
+public class VocabularyItemDocumentModelHandler
+        extends RemoteDocumentModelHandler<VocabularyitemsCommon, VocabularyitemsCommonList> {
+
+    private final Logger logger = LoggerFactory.getLogger(VocabularyItemDocumentModelHandler.class);
+    /**
+     * vocabularyItem is used to stash JAXB object to use when handle is called
+     * for Action.CREATE, Action.UPDATE or Action.GET
+     */
+    private VocabularyitemsCommon vocabularyItem;
+    /**
+     * vocabularyItemList is stashed when handle is called
+     * for ACTION.GET_ALL
+     */
+    private VocabularyitemsCommonList vocabularyItemList;
+    
+    /**
+     * inVocabulary is the parent vocabulary for this context
+     */
+    private String inVocabulary;
+
+    public String getInVocabulary() {
+               return inVocabulary;
+       }
+
+       public void setInVocabulary(String inVocabulary) {
+               this.inVocabulary = inVocabulary;
+       }
+
+       @Override
+    public void prepare(Action action) throws Exception {
+        //no specific action needed
+    }
+
+    /**
+     * getCommonPart get associated vocabularyItem
+     * @return
+     */
+    @Override
+    public VocabularyitemsCommon getCommonPart() {
+        return vocabularyItem;
+    }
+
+    /**
+     * setCommonPart set associated vocabularyItem
+     * @param vocabularyItem
+     */
+    @Override
+    public void setCommonPart(VocabularyitemsCommon vocabularyItem) {
+        this.vocabularyItem = vocabularyItem;
+    }
+
+    /**
+     * getCommonPartList get associated vocabularyItem (for index/GET_ALL)
+     * @return
+     */
+    @Override
+    public VocabularyitemsCommonList getCommonPartList() {
+        return vocabularyItemList;
+    }
+
+    @Override
+    public void setCommonPartList(VocabularyitemsCommonList vocabularyItemList) {
+        this.vocabularyItemList = vocabularyItemList;
+    }
+
+    @Override
+    public VocabularyitemsCommon extractCommonPart(DocumentWrapper wrapDoc)
+            throws Exception {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void fillCommonPart(VocabularyitemsCommon vocabularyItemObject, DocumentWrapper wrapDoc) throws Exception {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public VocabularyitemsCommonList extractCommonPartList(DocumentWrapper wrapDoc) 
+       throws Exception {
+        VocabularyitemsCommonList coList = new VocabularyitemsCommonList();
+        try{
+               DocumentModelList docList = (DocumentModelList) wrapDoc.getWrappedObject();
+       
+               List<VocabularyitemsCommonList.VocabularyitemListItem> list = 
+                       coList.getVocabularyitemListItem();
+       
+               //FIXME: iterating over a long list of documents is not a long term
+               //strategy...need to change to more efficient iterating in future
+               Iterator<DocumentModel> iter = docList.iterator();
+               while(iter.hasNext()){
+                   DocumentModel docModel = iter.next();
+                   String parentVocab = (String)docModel.getProperty(getServiceContext().getCommonPartLabel("vocabularyItems"),
+                           VocabularyItemJAXBSchema.IN_VOCABULARY); 
+                   if( !inVocabulary.equals(parentVocab))
+                       continue;
+                   VocabularyitemListItem ilistItem = new VocabularyitemListItem();
+                   ilistItem.setDisplayName((String) docModel.getProperty(getServiceContext().getCommonPartLabel("vocabularyItems"),
+                           VocabularyItemJAXBSchema.DISPLAY_NAME));
+                   String id = docModel.getId();
+                   ilistItem.setUri("/vocabularies/"+inVocabulary+"/items/" + id);
+                   ilistItem.setCsid(id);
+                   list.add(ilistItem);
+               }
+        }catch(Exception e){
+            if(logger.isDebugEnabled()){
+                logger.debug("Caught exception in extractCommonPartList", e);
+            }
+            throw e;
+        }
+        return coList;
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.collectionspace.services.nuxeo.client.java.DocumentModelHandler#getDocumentType()
+     */
+    @Override
+    public String getDocumentType() {
+        return VocabularyItemConstants.NUXEO_DOCTYPE;
+    }
+
+    /**
+     * getQProperty converts the given property to qualified schema property
+     * @param prop
+     * @return
+     */
+    @Override
+    public String getQProperty(String prop) {
+        return VocabularyItemConstants.NUXEO_SCHEMA_NAME + ":" + prop;
+    }
+}
+
diff --git a/services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/nuxeo/VocabularyItemHandlerFactory.java b/services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/nuxeo/VocabularyItemHandlerFactory.java
new file mode 100644 (file)
index 0000000..89440fa
--- /dev/null
@@ -0,0 +1,56 @@
+/**
+ *  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 University of California at Berkeley
+
+ *  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.vocabulary.nuxeo;
+
+import org.collectionspace.services.common.ClientType;
+import org.collectionspace.services.common.repository.DocumentHandler;
+import org.collectionspace.services.common.repository.DocumentHandlerFactory;
+
+
+/**
+ * VocabularyItemHandlerFactory creates handlers for vocabularyitem based
+ * on type of Nuxeo client used
+ *
+ * $LastChangedRevision: $
+ * $LastChangedDate: $
+ */
+public class VocabularyItemHandlerFactory implements DocumentHandlerFactory {
+
+    private static final VocabularyItemHandlerFactory self = new VocabularyItemHandlerFactory();
+
+    private VocabularyItemHandlerFactory() {
+    }
+
+    public static VocabularyItemHandlerFactory getInstance() {
+        return self;
+    }
+
+               @Override
+    public DocumentHandler getHandler(String clientType) {
+        if(ClientType.JAVA.toString().equals(clientType)){
+            return new VocabularyItemDocumentModelHandler();
+        } 
+        throw new IllegalArgumentException("Not supported client=" + clientType);
+    }
+}