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.Request;
38 import javax.ws.rs.core.UriInfo;
40 import org.collectionspace.services.client.PayloadOutputPart;
41 import org.collectionspace.services.client.PoxPayloadIn;
42 import org.collectionspace.services.client.PoxPayloadOut;
43 import org.collectionspace.services.client.workflow.WorkflowClient;
44 import org.collectionspace.services.common.context.MultipartServiceContext;
45 import org.collectionspace.services.common.context.MultipartServiceContextFactory;
46 import org.collectionspace.services.common.context.MultipartServiceContextImpl;
47 import org.collectionspace.services.common.context.ServiceContext;
48 import org.collectionspace.services.common.context.ServiceContextFactory;
49 import org.collectionspace.services.common.document.DocumentHandler;
50 import org.collectionspace.services.common.workflow.service.nuxeo.WorkflowDocumentModelHandler;
51 import org.collectionspace.services.lifecycle.Lifecycle;
52 import org.collectionspace.services.lifecycle.TransitionDef;
53 import org.collectionspace.services.nuxeo.util.NuxeoUtils;
54 import org.collectionspace.services.workflow.WorkflowCommon;
55 import org.dom4j.DocumentException;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
60 * The Class AbstractMultiPartCollectionSpaceResourceImpl.
62 public abstract class AbstractMultiPartCollectionSpaceResourceImpl extends AbstractCollectionSpaceResourceImpl<PoxPayloadIn, PoxPayloadOut> {
64 protected final Logger logger = LoggerFactory.getLogger(this.getClass());
67 public ServiceContextFactory<PoxPayloadIn, PoxPayloadOut> getServiceContextFactory() {
68 return MultipartServiceContextFactory.get();
71 abstract protected String getOrderByField(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx);
73 abstract protected String getPartialTermMatchField(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx);
76 public DocumentHandler createDocumentHandler(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx) throws Exception {
77 return createDocumentHandler(ctx, ctx.getCommonPartLabel(), getCommonPartClass());
81 * Creates the document handler.
83 * @param serviceContext the service context
84 * @param schemaName the schema name
85 * @param commonClass the common class
87 * @return the document handler
89 * @throws Exception the exception
91 public DocumentHandler createDocumentHandler(ServiceContext<PoxPayloadIn, PoxPayloadOut> serviceContext,
93 Class<?> commonClass) throws Exception {
94 DocumentHandler result = null;
96 MultipartServiceContext ctx = (MultipartServiceContext) serviceContext;
97 Object commonPart = null;
98 if (ctx.getInput() != null) {
99 commonPart = ctx.getInputPart(schemaName);
101 result = super.createDocumentHandler(ctx, commonPart);
107 * Creates the document handler.
110 * @param commonClass the common class
112 * @return the document handler
114 * @throws Exception the exception
116 public DocumentHandler createDocumentHandler(
117 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
118 Class<Object> commonClass) throws Exception {
119 return createDocumentHandler(ctx, ctx.getCommonPartLabel(), commonClass);
123 * Creates the contact document handler.
126 * @param inAuthority the in authority
127 * @param inItem the in item
129 * @return the document handler
131 * @throws Exception the exception
133 protected WorkflowDocumentModelHandler createWorkflowDocumentHandler(
134 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx) throws Exception {
136 WorkflowDocumentModelHandler docHandler = (WorkflowDocumentModelHandler) createDocumentHandler(ctx,
137 WorkflowClient.SERVICE_COMMONPART_NAME,
138 WorkflowCommon.class);
144 * Get the workflow lifecycle description of a resource
149 @Path(WorkflowClient.SERVICE_PATH)
150 public Lifecycle getWorkflow(@Context Request jaxRsRequest, @Context UriInfo uriInfo) {
153 String documentType = "undefined";
154 MultipartServiceContext ctx = null;
156 ctx = (MultipartServiceContext) createServiceContext(uriInfo);
157 DocumentHandler handler = ctx.getDocumentHandler();
158 result = handler.getLifecycle();
159 } catch (Exception e) {
160 throw bigReThrow(e, ServiceMessages.READ_FAILED + WorkflowClient.SERVICE_PAYLOAD_NAME, ctx.getDocumentType());
163 if (result == null) {
164 result = new Lifecycle();
165 result.setName("No life cycle defined for:" + documentType);
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 return getWorkflowWithExistingContext(null, uriInfo, csid);
182 public byte[] getWorkflowWithExistingContext(
183 ServiceContext<PoxPayloadIn, PoxPayloadOut> existingContext,
186 PoxPayloadOut result = null;
189 ServiceContext<PoxPayloadIn, PoxPayloadOut> parentCtx = createServiceContext(uriInfo);
190 String parentWorkspaceName = parentCtx.getRepositoryWorkspaceName();
192 MultipartServiceContext ctx = (MultipartServiceContext) createServiceContext(WorkflowClient.SERVICE_NAME, uriInfo);
193 if (existingContext != null && existingContext.getCurrentRepositorySession() != null) {
194 ctx.setCurrentRepositorySession(existingContext.getCurrentRepositorySession()); // Reuse the current repo session if one exists
196 WorkflowDocumentModelHandler handler = createWorkflowDocumentHandler(ctx);
197 ctx.setRespositoryWorkspaceName(parentWorkspaceName); //find the document in the parent's workspace
198 getRepositoryClient(ctx).get(ctx, csid, handler);
199 result = ctx.getOutput();
200 } catch (Exception e) {
201 throw bigReThrow(e, ServiceMessages.READ_FAILED + WorkflowClient.SERVICE_PAYLOAD_NAME, csid);
204 return result.getBytes();
207 protected TransitionDef getTransitionDef(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx, String transition) {
208 TransitionDef result = null;
212 lifecycle = ctx.getDocumentHandler().getLifecycle();
213 result = NuxeoUtils.getTransitionDef(lifecycle, transition);
214 } catch (Exception e) {
215 logger.error("Failed to get transition definition.", e);
221 private PoxPayloadIn synthEmptyWorkflowInput() {
222 PoxPayloadIn result = null;
224 PoxPayloadOut output = new PoxPayloadOut(WorkflowClient.SERVICE_PAYLOAD_NAME);
225 WorkflowCommon workflowCommons = new WorkflowCommon();
226 PayloadOutputPart commonPart = output.addPart(WorkflowClient.SERVICE_COMMONPART_NAME, workflowCommons);
227 String payloadXML = output.toXML();
229 result = new PoxPayloadIn(payloadXML);
230 } catch (DocumentException e) {
231 // TODO Auto-generated catch block
238 public PoxPayloadOut updateWorkflowWithTransition(ServiceContext existingContext,
243 PoxPayloadOut result = null;
246 MultipartServiceContextImpl workflowCtx = (MultipartServiceContextImpl)createServiceContext(WorkflowClient.SERVICE_NAME, uriInfo);
248 // Get properties out of the existing context if one was passed in
250 if (existingContext != null) {
251 if (existingContext.getCurrentRepositorySession() != null) {
252 workflowCtx.setCurrentRepositorySession(existingContext.getCurrentRepositorySession());
254 if (existingContext.getProperties() != null) {
255 workflowCtx.setProperties(existingContext.getProperties());
260 // Create an empty workflow_commons input part and set it into a new "workflow" sub-resource context
262 PoxPayloadIn input = new PoxPayloadIn(WorkflowClient.SERVICE_PAYLOAD_NAME, new WorkflowCommon(),
263 WorkflowClient.SERVICE_COMMONPART_NAME);
264 workflowCtx.setInput(input);
266 // Create a service context and document handler for the target resource.
267 ServiceContext<PoxPayloadIn, PoxPayloadOut> targetCtx = createServiceContext(workflowCtx.getUriInfo());
268 DocumentHandler targetDocHandler = createDocumentHandler(targetCtx);
269 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
271 // When looking for the document, we need to use the parent's workspace name -not the "workflow" workspace name
272 String targetWorkspaceName = targetCtx.getRepositoryWorkspaceName();
273 workflowCtx.setRespositoryWorkspaceName(targetWorkspaceName); //find the document in the parent's workspace
275 // Get the type of transition we're being asked to make and store it as a context parameter -used by the workflow document handler
276 TransitionDef transitionDef = getTransitionDef(targetCtx, transition);
277 if (transitionDef == null) {
278 throw new DocumentException(String.format("The document with ID='%s' does not support the workflow transition '%s'.",
281 workflowCtx.setProperty(WorkflowClient.TRANSITION_ID, transitionDef);
283 WorkflowDocumentModelHandler workflowHandler = createWorkflowDocumentHandler(workflowCtx);
284 getRepositoryClient(workflowCtx).update(workflowCtx, csid, workflowHandler);
285 result = workflowCtx.getOutput();
286 } catch (Exception e) {
287 throw bigReThrow(e, ServiceMessages.UPDATE_FAILED + WorkflowClient.SERVICE_PAYLOAD_NAME, csid);
295 * We should consider changing this code. The RepositoryClient (from call to getRepositoryClient) could support a call doWorkflowTransition() instead?
298 @Path("{csid}" + WorkflowClient.SERVICE_PATH + "/" + "{transition}")
299 public byte[] updateWorkflowWithTransition(
300 @Context UriInfo uriInfo,
301 @PathParam("csid") String csid,
302 @PathParam("transition") String transition) {
303 PoxPayloadOut result = null;
306 result = updateWorkflowWithTransition(NULL_CONTEXT, uriInfo, csid, transition);
307 } catch (Exception e) {
308 throw bigReThrow(e, ServiceMessages.UPDATE_FAILED + WorkflowClient.SERVICE_PAYLOAD_NAME, csid);
311 return result.getBytes();