2 * AbstractMultiPartCollectionSpaceResourceImpl.java
4 * {Purpose of This Class}
6 * {Other Notes Relating to This Class (Optional)}
9 * $LastChangedRevision: $
12 * This document is a part of the source code and related artifacts
13 * for CollectionSpace, an open source collections management system
14 * for museums and related institutions:
16 * http://www.collectionspace.org
17 * http://wiki.collectionspace.org
19 * Copyright © 2009 {Contributing Institution}
21 * Licensed under the Educational Community License (ECL), Version 2.0.
22 * You may not use this file except in compliance with this License.
24 * You may obtain a copy of the ECL 2.0 License at
25 * https://source.collectionspace.org/collection-space/LICENSE.txt
27 package org.collectionspace.services.common;
29 import java.util.Iterator;
30 import java.util.List;
32 import javax.ws.rs.GET;
33 import javax.ws.rs.PUT;
34 import javax.ws.rs.Path;
35 import javax.ws.rs.PathParam;
36 import javax.ws.rs.core.Context;
37 import javax.ws.rs.core.UriInfo;
39 import org.collectionspace.services.client.PayloadOutputPart;
40 import org.collectionspace.services.client.PoxPayloadIn;
41 import org.collectionspace.services.client.PoxPayloadOut;
42 import org.collectionspace.services.client.workflow.WorkflowClient;
43 import org.collectionspace.services.common.context.MultipartServiceContext;
44 import org.collectionspace.services.common.context.MultipartServiceContextFactory;
45 import org.collectionspace.services.common.context.ServiceContext;
46 import org.collectionspace.services.common.context.ServiceContextFactory;
47 import org.collectionspace.services.common.document.DocumentHandler;
48 import org.collectionspace.services.common.workflow.service.nuxeo.WorkflowDocumentModelHandler;
49 import org.collectionspace.services.lifecycle.Lifecycle;
50 import org.collectionspace.services.lifecycle.TransitionDef;
51 import org.collectionspace.services.workflow.WorkflowCommon;
52 import org.dom4j.DocumentException;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
58 * The Class AbstractMultiPartCollectionSpaceResourceImpl.
60 public abstract class AbstractMultiPartCollectionSpaceResourceImpl extends AbstractCollectionSpaceResourceImpl<PoxPayloadIn, PoxPayloadOut> {
62 protected final Logger logger = LoggerFactory.getLogger(this.getClass());
65 public ServiceContextFactory<PoxPayloadIn, PoxPayloadOut> getServiceContextFactory() {
66 return MultipartServiceContextFactory.get();
69 abstract protected String getOrderByField(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx);
71 abstract protected String getPartialTermMatchField(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx);
74 public DocumentHandler createDocumentHandler(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx) throws Exception {
75 return createDocumentHandler(ctx, ctx.getCommonPartLabel(), getCommonPartClass());
79 * Creates the document handler.
81 * @param serviceContext the service context
82 * @param schemaName the schema name
83 * @param commonClass the common class
85 * @return the document handler
87 * @throws Exception the exception
89 public DocumentHandler createDocumentHandler(ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
91 Class<?> commonClass) throws Exception {
92 DocumentHandler result = null;
94 MultipartServiceContext ctx = (MultipartServiceContext) serviceContext;
95 Object commonPart = null;
96 if (ctx.getInput() != null) {
97 commonPart = ctx.getInputPart(schemaName);
99 result = super.createDocumentHandler(ctx, commonPart);
105 * Creates the document handler.
108 * @param commonClass the common class
110 * @return the document handler
112 * @throws Exception the exception
114 public DocumentHandler createDocumentHandler(
115 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
116 Class<Object> commonClass) throws Exception {
117 return createDocumentHandler(ctx, ctx.getCommonPartLabel(), commonClass);
121 * Creates the contact document handler.
124 * @param inAuthority the in authority
125 * @param inItem the in item
127 * @return the document handler
129 * @throws Exception the exception
131 protected WorkflowDocumentModelHandler createWorkflowDocumentHandler(
132 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx) throws Exception {
134 WorkflowDocumentModelHandler docHandler = (WorkflowDocumentModelHandler) createDocumentHandler(ctx,
135 WorkflowClient.SERVICE_COMMONPART_NAME,
136 WorkflowCommon.class);
142 * JAX-RS Annotated methods
145 @Path(WorkflowClient.SERVICE_PATH)
146 public Lifecycle getWorkflow(@Context UriInfo uriInfo) {
149 String documentType = "undefined";
150 MultipartServiceContext ctx = null;
152 ctx = (MultipartServiceContext) createServiceContext(uriInfo);
153 DocumentHandler handler = ctx.getDocumentHandler();
154 result = handler.getLifecycle();
155 } catch (Exception e) {
156 throw bigReThrow(e, ServiceMessages.READ_FAILED + WorkflowClient.SERVICE_PAYLOAD_NAME, ctx.getDocumentType());
159 if (result == null) {
160 result = new Lifecycle();
161 result.setName("No life cycle defined for:" + documentType);
168 * JAX-RS Annotated methods
172 * We should change this method. The RepositoryClient (from call to getRepositoryClient) should support a call getWorkflowTransition() instead.
175 @Path("{csid}" + WorkflowClient.SERVICE_PATH)
176 public byte[] getWorkflow(
177 @Context UriInfo uriInfo,
178 @PathParam("csid") String csid) {
179 PoxPayloadOut result = null;
182 ServiceContext<PoxPayloadIn, PoxPayloadOut> parentCtx = createServiceContext(uriInfo);
183 String parentWorkspaceName = parentCtx.getRepositoryWorkspaceName();
185 MultipartServiceContext ctx = (MultipartServiceContext) createServiceContext(WorkflowClient.SERVICE_NAME, uriInfo);
186 WorkflowDocumentModelHandler handler = createWorkflowDocumentHandler(ctx);
187 ctx.setRespositoryWorkspaceName(parentWorkspaceName); //find the document in the parent's workspace
188 getRepositoryClient(ctx).get(ctx, csid, handler);
189 result = ctx.getOutput();
190 } catch (Exception e) {
191 throw bigReThrow(e, ServiceMessages.READ_FAILED + WorkflowClient.SERVICE_PAYLOAD_NAME, csid);
194 return result.getBytes();
197 protected TransitionDef getTransitionDef(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx, String transition) {
198 TransitionDef result = null;
201 Lifecycle lifecycle = ctx.getDocumentHandler().getLifecycle();
202 List<TransitionDef> transitionDefList = lifecycle.getTransitionDefList().getTransitionDef();
203 Iterator<TransitionDef> iter = transitionDefList.iterator();
204 boolean found = false;
205 while (iter.hasNext() && found == false) {
206 TransitionDef transitionDef = iter.next();
207 if (transitionDef.getName().equalsIgnoreCase(transition)) {
208 result = transitionDef;
212 } catch (Exception e) {
213 logger.error("Exception trying to retreive life cycle information for: " + ctx.getDocumentType());
219 private PoxPayloadIn synthEmptyWorkflowInput() {
220 PoxPayloadIn result = null;
222 PoxPayloadOut output = new PoxPayloadOut(WorkflowClient.SERVICE_PAYLOAD_NAME);
223 WorkflowCommon workflowCommons = new WorkflowCommon();
224 PayloadOutputPart commonPart = output.addPart(WorkflowClient.SERVICE_COMMONPART_NAME, workflowCommons);
225 String payloadXML = output.toXML();
227 result = new PoxPayloadIn(payloadXML);
228 } catch (DocumentException e) {
229 // TODO Auto-generated catch block
237 * We should change this code. The RepositoryClient (from call to getRepositoryClient) should support a call doWorkflowTransition() instead.
239 //FIXME: This method is almost identical to the method org.collectionspace.services.common.vocabulary.updateWorkflowWithTransition() so
240 // they should be consolidated -be DRY (don't repeat yourself).
243 @Path("{csid}" + WorkflowClient.SERVICE_PATH + "/" + "{transition}")
244 public byte[] updateWorkflowWithTransition(
245 @Context UriInfo uriInfo,
246 @PathParam("csid") String csid,
247 @PathParam("transition") String transition) {
248 PoxPayloadOut result = null;
252 // Create an empty workflow_commons input part and set it into a new "workflow" sub-resource context
253 PoxPayloadIn input = new PoxPayloadIn(WorkflowClient.SERVICE_PAYLOAD_NAME, new WorkflowCommon(),
254 WorkflowClient.SERVICE_COMMONPART_NAME);
255 MultipartServiceContext ctx = (MultipartServiceContext) createServiceContext(WorkflowClient.SERVICE_NAME, input, uriInfo);
257 // Create a service context and document handler for the parent resource.
258 ServiceContext<PoxPayloadIn, PoxPayloadOut> parentCtx = createServiceContext(uriInfo);
259 DocumentHandler targetDocHandler = this.createDocumentHandler(parentCtx);
260 ctx.setProperty(WorkflowClient.TARGET_DOCHANDLER, targetDocHandler); //added as a context param for the workflow document handler -it will call the parent's dochandler "prepareForWorkflowTranstion" method
262 // When looking for the document, we need to use the parent's workspace name -not the "workflow" workspace name
263 String targetWorkspaceName = parentCtx.getRepositoryWorkspaceName();
264 ctx.setRespositoryWorkspaceName(targetWorkspaceName); //find the document in the parent's workspace
266 // Get the type of transition we're being asked to make and store it as a context parameter -used by the workflow document handler
267 TransitionDef transitionDef = getTransitionDef(parentCtx, transition);
268 if (transitionDef == null) {
269 throw new DocumentException(String.format("The document with ID='%s' does not support the workflow transition '%s'.",
272 ctx.setProperty(WorkflowClient.TRANSITION_ID, transitionDef);
274 WorkflowDocumentModelHandler handler = createWorkflowDocumentHandler(ctx);
275 getRepositoryClient(ctx).update(ctx, csid, handler);
276 result = ctx.getOutput();
277 } catch (Exception e) {
278 throw bigReThrow(e, ServiceMessages.UPDATE_FAILED + WorkflowClient.SERVICE_PAYLOAD_NAME, csid);
280 return result.getBytes();