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 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;
202 lifecycle = ctx.getDocumentHandler().getLifecycle();
203 result = NuxeoUtils.getTransitionDef(lifecycle, transition);
204 } catch (Exception e) {
205 logger.error("Failed to get transition definition.", e);
211 private PoxPayloadIn synthEmptyWorkflowInput() {
212 PoxPayloadIn result = null;
214 PoxPayloadOut output = new PoxPayloadOut(WorkflowClient.SERVICE_PAYLOAD_NAME);
215 WorkflowCommon workflowCommons = new WorkflowCommon();
216 PayloadOutputPart commonPart = output.addPart(WorkflowClient.SERVICE_COMMONPART_NAME, workflowCommons);
217 String payloadXML = output.toXML();
219 result = new PoxPayloadIn(payloadXML);
220 } catch (DocumentException e) {
221 // TODO Auto-generated catch block
228 public PoxPayloadOut updateWorkflowWithTransition(ServiceContext existingContext,
233 PoxPayloadOut result = null;
236 MultipartServiceContextImpl workflowCtx = (MultipartServiceContextImpl)createServiceContext(WorkflowClient.SERVICE_NAME, uriInfo);
238 // Get properties out of the existing context if one was passed in
240 if (existingContext != null) {
241 if (existingContext.getCurrentRepositorySession() != null) {
242 workflowCtx.setCurrentRepositorySession(existingContext.getCurrentRepositorySession());
244 if (existingContext.getProperties() != null) {
245 workflowCtx.setProperties(existingContext.getProperties());
250 // Create an empty workflow_commons input part and set it into a new "workflow" sub-resource context
252 PoxPayloadIn input = new PoxPayloadIn(WorkflowClient.SERVICE_PAYLOAD_NAME, new WorkflowCommon(),
253 WorkflowClient.SERVICE_COMMONPART_NAME);
254 workflowCtx.setInput(input);
256 // Create a service context and document handler for the target resource.
257 ServiceContext<PoxPayloadIn, PoxPayloadOut> targetCtx = createServiceContext(workflowCtx.getUriInfo());
258 DocumentHandler targetDocHandler = createDocumentHandler(targetCtx);
259 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
261 // When looking for the document, we need to use the parent's workspace name -not the "workflow" workspace name
262 String targetWorkspaceName = targetCtx.getRepositoryWorkspaceName();
263 workflowCtx.setRespositoryWorkspaceName(targetWorkspaceName); //find the document in the parent's workspace
265 // Get the type of transition we're being asked to make and store it as a context parameter -used by the workflow document handler
266 TransitionDef transitionDef = getTransitionDef(targetCtx, transition);
267 if (transitionDef == null) {
268 throw new DocumentException(String.format("The document with ID='%s' does not support the workflow transition '%s'.",
271 workflowCtx.setProperty(WorkflowClient.TRANSITION_ID, transitionDef);
273 WorkflowDocumentModelHandler workflowHandler = createWorkflowDocumentHandler(workflowCtx);
274 getRepositoryClient(workflowCtx).update(workflowCtx, csid, workflowHandler);
275 result = workflowCtx.getOutput();
276 } catch (Exception e) {
277 throw bigReThrow(e, ServiceMessages.UPDATE_FAILED + WorkflowClient.SERVICE_PAYLOAD_NAME, csid);
285 * We should consider changing this code. The RepositoryClient (from call to getRepositoryClient) could support a call doWorkflowTransition() instead?
288 @Path("{csid}" + WorkflowClient.SERVICE_PATH + "/" + "{transition}")
289 public byte[] updateWorkflowWithTransition(
290 @Context UriInfo uriInfo,
291 @PathParam("csid") String csid,
292 @PathParam("transition") String transition) {
293 PoxPayloadOut result = null;
296 result = updateWorkflowWithTransition(NULL_CONTEXT, uriInfo, csid, transition);
297 } catch (Exception e) {
298 throw bigReThrow(e, ServiceMessages.UPDATE_FAILED + WorkflowClient.SERVICE_PAYLOAD_NAME, csid);
301 return result.getBytes();