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