--- /dev/null
+package org.collectionspace.hello.client;
+
+import javax.ws.rs.core.Response;
+
+import org.collectionspace.hello.CollectionObject;
+import org.collectionspace.hello.CollectionObjectList;
+
+import org.jboss.resteasy.client.ProxyFactory;
+import org.jboss.resteasy.plugins.providers.RegisterBuiltin;
+import org.jboss.resteasy.client.ClientResponse;
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
+
+/**
+ * A CollectionObjectClient.
+
+ * @version $Revision:$
+ */
+public class CollectionObjectClient {
+
+ private static final String HOST = "http://localhost:8080";
+ private static final String URI = "/helloworld/cspace-nuxeo";
+
+ /**
+ *
+ */
+ private static final CollectionObjectClient instance = new CollectionObjectClient();
+ /**
+ *
+ */
+ private CollectionObjectProxy collectionObjectProxy;
+
+ /**
+ *
+ * Default constructor for CollectionObjectClient class.
+ *
+ */
+ private CollectionObjectClient() {
+ ResteasyProviderFactory factory = ResteasyProviderFactory.getInstance();
+ RegisterBuiltin.register(factory);
+ collectionObjectProxy = ProxyFactory.create(CollectionObjectProxy.class, HOST + URI);
+ }
+
+ /**
+ * FIXME Comment this
+ *
+ * @return
+ */
+ public static CollectionObjectClient getInstance() {
+ return instance;
+ }
+
+ /**
+ * @return
+ * @see org.collectionspace.hello.client.CollectionObjectProxy#getCollectionObject()
+ */
+ public ClientResponse<CollectionObjectList> getCollectionObjectList() {
+ return collectionObjectProxy.getCollectionObjectList();
+ }
+
+ /**
+ * @param csid
+ * @return
+ * @see org.collectionspace.hello.client.CollectionObjectProxy#getCollectionObject(java.lang.String)
+ */
+ public ClientResponse<CollectionObject> getCollectionObject(String csid) {
+ return collectionObjectProxy.getCollectionObject(csid);
+ }
+
+ /**
+ * @param collectionobject
+ * @return
+ * @see org.collectionspace.hello.client.CollectionObjectProxy#createCollectionObject(org.collectionspace.hello.CollectionObject)
+ */
+ public ClientResponse<Response> createCollectionObject(CollectionObject collectionObject) {
+ return collectionObjectProxy.createCollectionObject(collectionObject);
+ }
+
+ /**
+ * @param csid
+ * @param collectionobject
+ * @return
+ * @see org.collectionspace.hello.client.CollectionObjectProxy#updateCollectionObject(java.lang.Long, org.collectionspace.hello.CollectionObject)
+ */
+ public ClientResponse<CollectionObject> updateCollectionObject(String csid, CollectionObject collectionObject) {
+ return collectionObjectProxy.updateCollectionObject(csid, collectionObject);
+ }
+
+ /**
+ * @param csid
+ * @return
+ * @see org.collectionspace.hello.client.CollectionObjectProxy#deleteCollectionObject(java.lang.Long)
+ */
+ public ClientResponse<Response> deleteCollectionObject(String csid) {
+ return collectionObjectProxy.deleteCollectionObject(csid);
+ }
+}
--- /dev/null
+package org.collectionspace.hello.client;
+
+import javax.ws.rs.Consumes;
+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.core.Response;
+
+import org.collectionspace.hello.CollectionObject;
+import org.collectionspace.hello.CollectionObjectList;
+import org.jboss.resteasy.client.ClientResponse;
+
+/**
+ * @version $Revision:$
+ */
+@Path("/collectionobjects/")
+@Produces({"application/xml"})
+@Consumes({"application/xml"})
+public interface CollectionObjectProxy {
+
+ @GET
+ ClientResponse<CollectionObjectList> getCollectionObjectList();
+
+ //(C)reate
+ @POST
+ ClientResponse<Response> createCollectionObject(CollectionObject co);
+
+ //(R)ead
+ @GET
+ @Path("/{csid}")
+ ClientResponse<CollectionObject> getCollectionObject(@PathParam("csid") String csid);
+
+ //(U)pdate
+ @PUT
+ @Path("/{csid}")
+ ClientResponse<CollectionObject> updateCollectionObject(@PathParam("csid") String csid, CollectionObject co);
+
+ //(D)elete
+ @DELETE
+ @Path("/{csid}")
+ ClientResponse<Response> deleteCollectionObject(@PathParam("csid") String csid);
+}
\ No newline at end of file
--- /dev/null
+package org.collectionspace.hello.client.test;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Marshaller;
+import org.jboss.resteasy.client.ClientResponse;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import org.collectionspace.hello.CollectionObject;
+import org.collectionspace.hello.CollectionObjectList;
+import org.collectionspace.hello.client.CollectionObjectClient;
+
+/**
+ * A CollectionObjectNuxeoServiceTest.
+ *
+ * @version $Revision:$
+ */
+public class CollectionObjectServiceTest {
+
+ private CollectionObjectClient collectionObjectClient = CollectionObjectClient.getInstance();
+ private String updateId = null;
+ private String deleteId = null;
+
+ @Test
+ public void createCollectionObject() {
+ long identifier = this.createIdentifier();
+
+ CollectionObject collectionObject = createCollectionObject(identifier);
+ ClientResponse<Response> res = collectionObjectClient.createCollectionObject(collectionObject);
+ Assert.assertEquals(res.getStatus(), Response.Status.CREATED.getStatusCode());
+
+ //store updateId locally for "update" test
+ if (updateId == null)
+ updateId = extractId(res);
+ else
+ deleteId = extractId(res);
+ }
+
+ @Test(dependsOnMethods = {"createCollectionObject"})
+ public void updateCollectionObject() {
+ ClientResponse<CollectionObject> res = collectionObjectClient.getCollectionObject(updateId);
+ CollectionObject collectionObject = res.getEntity();
+ verbose("got collectionobject to update: " + updateId,
+ collectionObject, CollectionObject.class);
+
+ //collectionObject.setCsid("updated-" + updateId);
+ collectionObject.setIdentifier("updated-" + collectionObject.getIdentifier());
+ collectionObject.setDescription("updated-" + collectionObject.getDescription());
+
+ res = collectionObjectClient.updateCollectionObject(updateId, collectionObject);
+ CollectionObject updatedCollectionObject = res.getEntity();
+ Assert.assertEquals(updatedCollectionObject.getDescription(), collectionObject.getDescription());
+
+ verbose("updated collectionObject", updatedCollectionObject, CollectionObject.class);
+
+ return;
+ }
+
+ @Test(dependsOnMethods = {"createCollectionObject"})
+ public void createCollection() {
+ for (int i = 0; i < 3; i++) {
+ this.createCollectionObject();
+ }
+ }
+
+ @Test(dependsOnMethods = {"createCollection"})
+ public void getCollectionObjectList() {
+ //the resource method is expected to return at least an empty list
+ CollectionObjectList coList = collectionObjectClient.getCollectionObjectList().getEntity();
+ List<CollectionObjectList.CollectionObjectListItem> coItemList = coList.getCollectionObjectListItem();
+ int i = 0;
+ for(CollectionObjectList.CollectionObjectListItem pli : coItemList) {
+ verbose("getCollectionObjectList: list-item[" + i + "] csid=" + pli.getCsid());
+ verbose("getCollectionObjectList: list-item[" + i + "] identifier=" + pli.getIdentifier());
+ verbose("getCollectionObjectList: list-item[" + i + "] URI=" + pli.getUri());
+ i++;
+ }
+ }
+
+ @Test(dependsOnMethods = {"updateCollectionObject"})
+ public void deleteCollectionObject() {
+ ClientResponse<Response> res = collectionObjectClient.deleteCollectionObject(deleteId);
+ verbose("deleteCollectionObject: csid=" + deleteId);
+ verbose("deleteCollectionObject: status = " + res.getStatus());
+ Assert.assertEquals(res.getStatus(), Response.Status.NO_CONTENT.getStatusCode());
+ }
+
+ private CollectionObject createCollectionObject(String csid, String identifier, String description) {
+ CollectionObject collectionObject = new CollectionObject();
+
+ collectionObject.setCsid(csid);
+ collectionObject.setIdentifier(identifier);
+ collectionObject.setDescription(description);
+
+ return collectionObject;
+ }
+
+ private CollectionObject createCollectionObject(long identifier) {
+ CollectionObject collectionObject = createCollectionObject("csid-" + identifier,
+ "did-" + identifier, "description-" + identifier);
+
+ return collectionObject;
+ }
+
+ private String extractId(ClientResponse<Response> res) {
+ MultivaluedMap mvm = res.getMetadata();
+ String uri = (String) ((ArrayList) mvm.get("Location")).get(0);
+ String[] segments = uri.split("/");
+ String id = segments[segments.length - 1];
+ verbose("id=" + id);
+ return id;
+ }
+
+ private void verbose(String msg) {
+ System.out.println("CollectionObjectServiceTest : " + msg);
+ }
+
+ private void verbose(String msg, Object o, Class clazz) {
+ try{
+ verbose(msg);
+ JAXBContext jc = JAXBContext.newInstance(clazz);
+ Marshaller m = jc.createMarshaller();
+ m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
+ Boolean.TRUE);
+ m.marshal(o, System.out);
+ }catch(Exception e){
+ e.printStackTrace();
+ }
+ }
+
+ private void verboseMap(MultivaluedMap map) {
+ for(Object entry : map.entrySet()){
+ MultivaluedMap.Entry mentry = (MultivaluedMap.Entry) entry;
+ verbose(" name=" + mentry.getKey() + " value=" + mentry.getValue());
+ }
+ }
+
+ private long createIdentifier() {
+ long identifier = System.currentTimeMillis();
+ return identifier;
+ }
+}
--- /dev/null
+package org.collectionspace.hello.services;
+
+import java.io.ByteArrayInputStream;
+import org.collectionspace.hello.services.nuxeo.NuxeoRESTClient;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import java.util.Map;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Marshaller;
+import org.collectionspace.hello.*;
+
+
+import org.collectionspace.hello.CollectionObjectList.CollectionObjectListItem;
+import org.dom4j.Document;
+import org.dom4j.Element;
+import org.dom4j.Namespace;
+import org.dom4j.io.SAXReader;
+import org.restlet.resource.Representation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Path("/collectionobjects")
+@Consumes("application/xml")
+@Produces("application/xml")
+public class CollectionObjectResource {
+
+ final static String NUXEO_WORKSPACE_UID = "776a8787-9d81-41b0-a02c-1ba674638c0a";
+ final static String NUXEO_DOCTYPE = "CollectionObject";
+
+ final Logger logger = LoggerFactory.getLogger(CollectionObjectResource.class);
+
+ public CollectionObjectResource() {
+ // do nothing
+ }
+
+ @GET
+ public CollectionObjectList getCollectionObjectList(@Context UriInfo ui) {
+ CollectionObjectList p = new CollectionObjectList();
+ try{
+ List<CollectionObjectList.CollectionObjectListItem> list = p.getCollectionObjectListItem();
+ NuxeoRESTClient nxClient = getClient();
+
+ List<String> pathParams = new ArrayList<String>();
+ Map<String, String> queryParams = new HashMap<String, String>();
+ pathParams = Arrays.asList("default", NUXEO_WORKSPACE_UID, "browse");
+ Representation res = nxClient.get(pathParams, queryParams);
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(res.getStream());
+ Element root = document.getRootElement();
+ for(Iterator i = root.elementIterator(); i.hasNext();){
+ Element element = (Element) i.next();
+ CollectionObjectListItem pli = new CollectionObjectListItem();
+ //
+ pli.setCsid(element.attributeValue("csid"));
+ pli.setUri(element.attributeValue("url"));
+ pli.setIdentifier(element.attributeValue("identifier"));
+ list.add(pli);
+ }
+
+ }catch(Exception e){
+ e.printStackTrace();
+ }
+ return p;
+ }
+
+ @POST
+ public Response createCollectionObject(CollectionObject co) {
+
+ NuxeoRESTClient nxClient = getClient();
+
+ List<String> pathParams = new ArrayList<String>();
+ Map<String, String> queryParams = new HashMap<String, String>();
+ pathParams.add("default");
+ pathParams.add(NUXEO_WORKSPACE_UID);
+ pathParams.add("createDocument");
+ queryParams.put("docType", NUXEO_DOCTYPE);
+
+ queryParams.put("dublincore:title", co.getIdentifier());
+ // CollectionObject core values
+ queryParams.put("collectionobject:csid", Integer.valueOf(1).toString());
+ queryParams.put("collectionobject:identifier", co.getIdentifier());
+ queryParams.put("collectionobject:description", co.getDescription());
+
+ ByteArrayInputStream bais = new ByteArrayInputStream(new byte[0]);
+ Representation res = nxClient.post(pathParams, queryParams, bais);
+
+ SAXReader reader = new SAXReader();
+ try {
+ Document document = reader.read(res.getStream());
+ Element root = document.getRootElement();
+ for (Iterator i = root.elementIterator(); i.hasNext();){
+ Element element = (Element) i.next();
+ if ("docRef".equals(element.getName())){
+ String id = (String) element.getData();
+ co.setCsid(id);
+ }
+ }
+ } catch(Exception e){
+ Response response = Response.status(Response.Status.NOT_FOUND).entity(
+ "Create failed").type("text/plain").build();
+ throw new WebApplicationException(response);
+ }
+
+ verbose("created collectionobject", co);
+ UriBuilder path = UriBuilder.fromResource(PersonNuxeoResource.class);
+ path.path("" + co.getCsid());
+ Response response = Response.created(path.build()).build();
+
+ return response;
+ }
+
+ @GET
+ @Path("{csid}")
+ public CollectionObject getCollectionObject(@PathParam("csid") String csid) {
+
+ CollectionObject co = null;
+ try {
+ List<String> pathParams = new ArrayList<String>();
+ Map<String, String> queryParams = new HashMap<String, String>();
+
+ pathParams.add("default");
+ pathParams.add(csid);
+ pathParams.add("export");
+ queryParams.put("format", "XML");
+
+ NuxeoRESTClient nxClient = getClient();
+ Representation res = nxClient.get(pathParams, queryParams);
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(res.getStream());
+ Element root = document.getRootElement();
+ co = new CollectionObject();
+
+ // TODO: recognize schema thru namespace uri
+// Namespace ns = new Namespace("collectionobject", "http://collectionspace.org/collectionobject");
+
+ Iterator<Element> siter = root.elementIterator("schema");
+ while (siter.hasNext()) {
+
+ Element schemaElement = siter.next();
+ System.err.println("CollectionObject.getCollectionObject() called.");
+
+ //TODO: recognize schema thru namespace uri
+ if ("collectionobject".equals(schemaElement.attribute("name").getValue())){
+ co.setCsid(csid);
+ Element ele = schemaElement.element("identifier");
+ if(ele != null){
+ co.setIdentifier((String) ele.getData());
+ }
+ ele = schemaElement.element("description");
+ if(ele != null){
+ co.setDescription((String) ele.getData());
+ }
+ }
+ }
+
+ } catch(Exception e){
+ e.printStackTrace();
+ Response response = Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
+ "Get failed").type("text/plain").build();
+ throw new WebApplicationException(response);
+ }
+ if (co == null) {
+ Response response = Response.status(Response.Status.NOT_FOUND).entity(
+ "Get failed, the requested CollectionObject CSID:" + csid + ": was not found.").type("text/plain").build();
+ throw new WebApplicationException(response);
+ }
+ verbose("get collectionobject", co);
+
+ return co;
+ }
+
+ @PUT
+ @Path("{csid}")
+ public CollectionObject updateCollectionObject(
+ @PathParam("csid") String csid,
+ CollectionObject update) {
+
+ verbose("updating collectionobject input", update);
+
+ List<String> pathParams = new ArrayList<String>();
+ Map<String, String> queryParams = new HashMap<String, String>();
+ pathParams.add("default");
+ pathParams.add(update.getCsid());
+ pathParams.add("updateDocumentRestlet");
+
+ //todo: intelligent merge needed
+ if(update.getIdentifier() != null){
+ queryParams.put("collectionobject:identifier", update.getIdentifier());
+ }
+
+ if(update.getDescription() != null){
+ queryParams.put("collectionobject:description", update.getDescription());
+ }
+
+ NuxeoRESTClient nxClient = getClient();
+ Representation res = nxClient.get(pathParams, queryParams);
+ SAXReader reader = new SAXReader();
+ String status = "";
+ try {
+ Document document = reader.read(res.getStream());
+ Element root = document.getRootElement();
+ for(Iterator i = root.elementIterator(); i.hasNext();){
+ Element element = (Element) i.next();
+ if("docRef".equals(element.getName())){
+ status = (String) element.getData();
+ verbose("update collectionobject: response=" + status);
+ }
+
+ }
+ } catch(Exception e) {
+ //FIXME: NOT_FOUND?
+ Response response = Response.status(Response.Status.NOT_FOUND).entity(
+ "Update failed ").type("text/plain").build();
+ throw new WebApplicationException(response);
+ }
+
+ return update;
+ }
+
+ @DELETE
+ @Path("{csid}")
+ public void deleteCollectionObject(@PathParam("csid") String csid) {
+
+ verbose("deleting collectionobject with csid=" + csid);
+
+ NuxeoRESTClient nxClient = getClient();
+ List<String> pathParams = new ArrayList<String>();
+ Map<String, String> queryParams = new HashMap<String, String>();
+
+ pathParams.add("default");
+ pathParams.add(csid);
+ pathParams.add("deleteDocumentRestlet");
+ Representation res = nxClient.get(pathParams, queryParams);
+ SAXReader reader = new SAXReader();
+ String status = "";
+
+ try {
+ Document document = reader.read(res.getStream());
+ Element root = document.getRootElement();
+ for(Iterator i = root.elementIterator(); i.hasNext();){
+ Element element = (Element) i.next();
+ if("docRef".equals(element.getName())){
+ status = (String) element.getData();
+ verbose("delete collectionobject: response=" + status);
+ }
+
+ }
+ }catch(Exception e){
+ //FIXME: NOT_FOUND?
+ Response response = Response.status(Response.Status.NOT_FOUND).entity(
+ "Delete failed ").type("text/plain").build();
+ throw new WebApplicationException(response);
+ }
+
+ }
+
+ private void verbose(String msg, CollectionObject co) {
+ try {
+ verbose(msg);
+ JAXBContext jc = JAXBContext.newInstance(
+ CollectionObject.class);
+
+ Marshaller m = jc.createMarshaller();
+ m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
+ Boolean.TRUE);
+ m.marshal(co, System.out);
+ } catch(Exception e){
+ e.printStackTrace();
+ }
+
+ }
+
+ private NuxeoRESTClient getClient() {
+ NuxeoRESTClient nxClient = new NuxeoRESTClient("http://127.0.0.1:8080/nuxeo");
+ nxClient.setAuthType(NuxeoRESTClient.AUTH_TYPE_BASIC);
+ nxClient.setBasicAuthentication("Administrator", "Administrator");
+ return nxClient;
+ }
+
+ private void verbose(String msg) {
+ System.out.println("CollectionObjectResource: " + msg);
+ }
+}
private Set<Class<?>> empty = new HashSet<Class<?>>();
public HelloworldNuxeoApplication() {
+ singletons.add(new CollectionObjectResource());
+ singletons.add(new IdentifierResource());
singletons.add(new PersonNuxeoResource());
}
--- /dev/null
+package org.collectionspace.hello.services;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+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.Response;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+import javax.ws.rs.core.UriBuilder;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Marshaller;
+import org.collectionspace.hello.Identifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Path("/identifiers")
+@Consumes("application/xml")
+@Produces("application/xml")
+public class IdentifierResource {
+
+ final Logger logger = LoggerFactory.getLogger(IdentifierResource.class);
+ private Map<Long, Identifier> idDB = new ConcurrentHashMap<Long, Identifier>();
+ private AtomicLong idCounter = new AtomicLong();
+
+ public IdentifierResource() {
+ // do nothing
+ }
+
+ @POST
+ public Response createIdentifier(Identifier id) {
+ if (id.getNamespace() == null) {
+ id.setNamespace("edu.berkeley");
+ }
+ id.setId(idCounter.incrementAndGet());
+ id.setVersion(1);
+ UUID uuid = UUID.nameUUIDFromBytes(id.getNamespace().getBytes());
+ id.setValue(uuid.toString());
+ idDB.put(id.getId(), id);
+ verbose("created Id", id);
+ UriBuilder path = UriBuilder.fromResource(IdentifierResource.class);
+ path.path("" + id.getId());
+ Response response = Response.created(path.build()).build();
+ return response;
+ }
+
+ @GET
+ @Path("{id}")
+ public Identifier getIdentifier(@PathParam("id") Long id) {
+ Identifier i = idDB.get(id);
+ if (i == null) {
+ Response response = Response.status(Response.Status.NOT_FOUND).entity(
+ "The requested ID was not found.").type("text/plain").build();
+ throw new WebApplicationException(response);
+ }
+ verbose("get Id", i);
+ return i;
+ }
+
+ private void verbose(String msg, Identifier id) {
+ try {
+ System.out.println("IdentifierResource : " + msg);
+ JAXBContext jc = JAXBContext.newInstance(Identifier.class);
+ Marshaller m = jc.createMarshaller();
+ m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
+ Boolean.TRUE);
+ m.marshal(id, System.out);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}