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.MultipartServiceContextImpl;
46 import org.collectionspace.services.common.context.ServiceContext;
47 import org.collectionspace.services.common.context.ServiceContextFactory;
48 import org.collectionspace.services.common.document.DocumentHandler;
49 import org.collectionspace.services.common.workflow.service.nuxeo.WorkflowDocumentModelHandler;
50 import org.collectionspace.services.lifecycle.Lifecycle;
51 import org.collectionspace.services.lifecycle.TransitionDef;
52 import org.collectionspace.services.workflow.WorkflowCommon;
54 import org.dom4j.DocumentException;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
59 * The Class AbstractMultiPartCollectionSpaceResourceImpl.
61 public abstract class AbstractMultiPartCollectionSpaceResourceImpl extends AbstractCollectionSpaceResourceImpl<PoxPayloadIn, PoxPayloadOut> {
63 protected final Logger logger = LoggerFactory.getLogger(this.getClass());
66 public ServiceContextFactory<PoxPayloadIn, PoxPayloadOut> getServiceContextFactory() {
67 return MultipartServiceContextFactory.get();
70 abstract protected String getOrderByField(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx);
72 abstract protected String getPartialTermMatchField(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx);
75 public DocumentHandler createDocumentHandler(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx) throws Exception {
76 return createDocumentHandler(ctx, ctx.getCommonPartLabel(), getCommonPartClass());
80 * Creates the document handler.
82 * @param serviceContext the service context
83 * @param schemaName the schema name
84 * @param commonClass the common class
86 * @return the document handler
88 * @throws Exception the exception
90 public DocumentHandler createDocumentHandler(ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
92 Class<?> commonClass) throws Exception {
93 DocumentHandler result = null;
95 MultipartServiceContext ctx = (MultipartServiceContext) serviceContext;
96 Object commonPart = null;
97 if (ctx.getInput() != null) {
98 commonPart = ctx.getInputPart(schemaName);
100 result = super.createDocumentHandler(ctx, commonPart);
106 * Creates the document handler.
109 * @param commonClass the common class
111 * @return the document handler
113 * @throws Exception the exception
115 public DocumentHandler createDocumentHandler(
116 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
117 Class<Object> commonClass) throws Exception {
118 return createDocumentHandler(ctx, ctx.getCommonPartLabel(), commonClass);
122 * Creates the contact document handler.
125 * @param inAuthority the in authority
126 * @param inItem the in item
128 * @return the document handler
130 * @throws Exception the exception
132 protected WorkflowDocumentModelHandler createWorkflowDocumentHandler(
133 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx) throws Exception {
135 WorkflowDocumentModelHandler docHandler = (WorkflowDocumentModelHandler) createDocumentHandler(ctx,
136 WorkflowClient.SERVICE_COMMONPART_NAME,
137 WorkflowCommon.class);
143 * Get the workflow lifecycle description of a resource
148 @Path(WorkflowClient.SERVICE_PATH)
149 public Lifecycle getWorkflow(@Context UriInfo uriInfo) {
152 String documentType = "undefined";
153 MultipartServiceContext ctx = null;
155 ctx = (MultipartServiceContext) createServiceContext(uriInfo);
156 DocumentHandler handler = ctx.getDocumentHandler();
157 result = handler.getLifecycle();
158 } catch (Exception e) {
159 throw bigReThrow(e, ServiceMessages.READ_FAILED + WorkflowClient.SERVICE_PAYLOAD_NAME, ctx.getDocumentType());
162 if (result == null) {
163 result = new Lifecycle();
164 result.setName("No life cycle defined for:" + documentType);
171 * We should change this method. The RepositoryClient (from call to getRepositoryClient) should support a call getWorkflowTransition() instead.
174 @Path("{csid}" + WorkflowClient.SERVICE_PATH)
175 public byte[] getWorkflow(
176 @Context UriInfo uriInfo,
177 @PathParam("csid") String csid) {
178 PoxPayloadOut result = null;
181 ServiceContext<PoxPayloadIn, PoxPayloadOut> parentCtx = createServiceContext(uriInfo);
182 String parentWorkspaceName = parentCtx.getRepositoryWorkspaceName();
184 MultipartServiceContext ctx = (MultipartServiceContext) createServiceContext(WorkflowClient.SERVICE_NAME, uriInfo);
185 WorkflowDocumentModelHandler handler = createWorkflowDocumentHandler(ctx);
186 ctx.setRespositoryWorkspaceName(parentWorkspaceName); //find the document in the parent's workspace
187 getRepositoryClient(ctx).get(ctx, csid, handler);
188 result = ctx.getOutput();
189 } catch (Exception e) {
190 throw bigReThrow(e, ServiceMessages.READ_FAILED + WorkflowClient.SERVICE_PAYLOAD_NAME, csid);
193 return result.getBytes();
196 protected TransitionDef getTransitionDef(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx, String transition) {
197 TransitionDef result = null;
200 Lifecycle lifecycle = ctx.getDocumentHandler().getLifecycle();
201 List<TransitionDef> transitionDefList = lifecycle.getTransitionDefList().getTransitionDef();
202 Iterator<TransitionDef> iter = transitionDefList.iterator();
203 boolean found = false;
204 while (iter.hasNext() && found == false) {
205 TransitionDef transitionDef = iter.next();
206 if (transitionDef.getName().equalsIgnoreCase(transition)) {
207 result = transitionDef;
211 } catch (Exception e) {
212 logger.error("Exception trying to retreive life cycle information for: " + ctx.getDocumentType());
218 private PoxPayloadIn synthEmptyWorkflowInput() {
219 PoxPayloadIn result = null;
221 PoxPayloadOut output = new PoxPayloadOut(WorkflowClient.SERVICE_PAYLOAD_NAME);
222 WorkflowCommon workflowCommons = new WorkflowCommon();
223 PayloadOutputPart commonPart = output.addPart(WorkflowClient.SERVICE_COMMONPART_NAME, workflowCommons);
224 String payloadXML = output.toXML();
226 result = new PoxPayloadIn(payloadXML);
227 } catch (DocumentException e) {
228 // TODO Auto-generated catch block
235 public PoxPayloadOut updateWorkflowWithTransition(ServiceContext existingContext,
240 PoxPayloadOut result = null;
243 MultipartServiceContextImpl workflowCtx = (MultipartServiceContextImpl)createServiceContext(WorkflowClient.SERVICE_NAME, uriInfo);
245 // Get properties out of the existing context if one was passed in
247 if (existingContext != null) {
248 if (existingContext.getCurrentRepositorySession() != null) {
249 workflowCtx.setCurrentRepositorySession(existingContext.getCurrentRepositorySession());
251 if (existingContext.getProperties() != null) {
252 workflowCtx.setProperties(existingContext.getProperties());
257 // Create an empty workflow_commons input part and set it into a new "workflow" sub-resource context
259 PoxPayloadIn input = new PoxPayloadIn(WorkflowClient.SERVICE_PAYLOAD_NAME, new WorkflowCommon(),
260 WorkflowClient.SERVICE_COMMONPART_NAME);
261 workflowCtx.setInput(input);
263 // Create a service context and document handler for the target resource.
264 ServiceContext<PoxPayloadIn, PoxPayloadOut> targetCtx = createServiceContext(workflowCtx.getUriInfo());
265 DocumentHandler targetDocHandler = createDocumentHandler(targetCtx);
266 workflowCtx.setProperty(WorkflowClient.TARGET_DOCHANDLER, targetDocHandler); //added as a context param for the workflow document handler -it will call the parent's dochandler "prepareForWorkflowTranstion" method
268 // When looking for the document, we need to use the parent's workspace name -not the "workflow" workspace name
269 String targetWorkspaceName = targetCtx.getRepositoryWorkspaceName();
270 workflowCtx.setRespositoryWorkspaceName(targetWorkspaceName); //find the document in the parent's workspace
272 // Get the type of transition we're being asked to make and store it as a context parameter -used by the workflow document handler
273 TransitionDef transitionDef = getTransitionDef(targetCtx, transition);
274 if (transitionDef == null) {
275 throw new DocumentException(String.format("The document with ID='%s' does not support the workflow transition '%s'.",
278 workflowCtx.setProperty(WorkflowClient.TRANSITION_ID, transitionDef);
280 WorkflowDocumentModelHandler workflowHandler = createWorkflowDocumentHandler(workflowCtx);
281 getRepositoryClient(workflowCtx).update(workflowCtx, csid, workflowHandler);
282 result = workflowCtx.getOutput();
283 } catch (Exception e) {
284 throw bigReThrow(e, ServiceMessages.UPDATE_FAILED + WorkflowClient.SERVICE_PAYLOAD_NAME, csid);
292 * We should consider changing this code. The RepositoryClient (from call to getRepositoryClient) could support a call doWorkflowTransition() instead?
295 @Path("{csid}" + WorkflowClient.SERVICE_PATH + "/" + "{transition}")
296 public byte[] updateWorkflowWithTransition(
297 @Context UriInfo uriInfo,
298 @PathParam("csid") String csid,
299 @PathParam("transition") String transition) {
300 PoxPayloadOut result = null;
303 result = this.updateWorkflowWithTransition(NULL_CONTEXT, uriInfo, csid, transition);
304 } catch (Exception e) {
305 throw bigReThrow(e, ServiceMessages.UPDATE_FAILED + WorkflowClient.SERVICE_PAYLOAD_NAME, csid);
308 return result.getBytes();