]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
696bc4641394980e1698b2f006b334399ed5cb6e
[tmp/jakarta-migration.git] /
1 /**
2  *  This document is a part of the source code and related artifacts
3  *  for CollectionSpace, an open source collections management system
4  *  for museums and related institutions:
5
6  *  http://www.collectionspace.org
7  *  http://wiki.collectionspace.org
8
9  *  Copyright 2009 University of California at Berkeley
10
11  *  Licensed under the Educational Community License (ECL), Version 2.0.
12  *  You may not use this file except in compliance with this License.
13
14  *  You may obtain a copy of the ECL 2.0 License at
15
16  *  https://source.collectionspace.org/collection-space/LICENSE.txt
17
18  *  Unless required by applicable law or agreed to in writing, software
19  *  distributed under the License is distributed on an "AS IS" BASIS,
20  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  *  See the License for the specific language governing permissions and
22  *  limitations under the License.
23  */
24 package org.collectionspace.services.common.workflow.service.nuxeo;
25
26 import java.util.Collection;
27 import java.util.HashMap;
28 import java.util.Map;
29
30 import javax.ws.rs.core.MediaType;
31
32 import org.collectionspace.services.client.workflow.WorkflowClient;
33 import org.collectionspace.services.common.context.MultipartServiceContext;
34 import org.collectionspace.services.common.context.ServiceContext;
35 import org.collectionspace.services.common.document.DocumentWrapper;
36 import org.collectionspace.services.common.workflow.jaxb.WorkflowJAXBSchema;
37 import org.collectionspace.services.config.service.ObjectPartType;
38 import org.collectionspace.services.lifecycle.TransitionDef;
39 import org.collectionspace.services.nuxeo.client.java.NuxeoDocumentModelHandler;
40 import org.collectionspace.services.nuxeo.client.java.DocumentModelHandler;
41 import org.collectionspace.services.workflow.WorkflowCommon;
42 import org.nuxeo.ecm.core.api.ClientException;
43 import org.nuxeo.ecm.core.api.DocumentModel;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 public class WorkflowDocumentModelHandler
48         extends NuxeoDocumentModelHandler<WorkflowCommon> {
49
50     /** The logger. */
51     private static final Logger logger = LoggerFactory.getLogger(WorkflowDocumentModelHandler.class);
52     /*
53      * Workflow transitions
54      *
55      * See the "Nuxeo core default life cycle definition", an XML configuration
56      * for Nuxeo's "lifecycle" extension point that specifies valid workflow
57      * states and the operations that transition documents to those states, via:
58      *
59      * org.nuxeo.ecm.core.LifecycleCoreExtensions--lifecycle (as opposed to --types)
60      */
61     private static final String TRANSITION_UNKNOWN = "unknown";
62
63     
64     @Override
65     public void handleUpdate(DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
66         //
67         // First, call the parent document handler to give it a chance to handle the workflow transition -otherwise, call
68         // the super/parent handleUpdate() method.
69         //
70         ServiceContext ctx = this.getServiceContext();
71         DocumentModelHandler targetDocHandler = (DocumentModelHandler)ctx.getProperty(WorkflowClient.TARGET_DOCHANDLER);
72         targetDocHandler.setRepositorySession(this.getRepositorySession()); // Make sure the target doc handler has a repository session to work with
73         TransitionDef transitionDef =  (TransitionDef)ctx.getProperty(WorkflowClient.TRANSITION_ID);
74         targetDocHandler.handleWorkflowTransition(wrapDoc, transitionDef);  // Call the target resouce's handler first
75         //
76         // If no exception occurred, then call the super's method
77         //
78         super.handleUpdate(wrapDoc);
79     }
80     
81     @Override
82     protected void handleRefNameChanges(ServiceContext ctx, DocumentModel docModel) throws ClientException {
83         //
84         // We are intentionally overriding this method to do nothing since the Workflow resource is a meta-resource without a refname
85         //
86     }    
87     
88     /*
89      * Handle read (GET)
90      */
91     @Override
92     protected Map<String, Object> extractPart(DocumentModel docModel,
93             String schema,
94             ObjectPartType partMeta,
95             Map<String, Object> addToMap)
96             throws Exception {
97         Map<String, Object> result = null;
98
99         MediaType mt = MediaType.valueOf(partMeta.getContent().getContentType()); //FIXME: REM - This is no longer needed.  Everything is POX
100         if (mt.equals(MediaType.APPLICATION_XML_TYPE)) {
101             Map<String, Object> unQObjectProperties =
102                     (addToMap != null) ? addToMap : (new HashMap<String, Object>());
103             unQObjectProperties.put(WorkflowJAXBSchema.WORKFLOW_LIFECYCLEPOLICY, docModel.getLifeCyclePolicy());
104             unQObjectProperties.put(WorkflowJAXBSchema.WORKFLOW_CURRENTLIFECYCLESTATE, docModel.getCurrentLifeCycleState());
105             result = unQObjectProperties;
106         } //TODO: handle other media types
107
108         return result;
109     }
110
111     @Override
112     public void extractAllParts(DocumentWrapper<DocumentModel> wrapDoc)
113             throws Exception {
114         DocumentModel docModel = wrapDoc.getWrappedObject();
115         String[] schemas = {WorkflowClient.SERVICE_COMMONPART_NAME};
116         Map<String, ObjectPartType> partsMetaMap = getServiceContext().getPartsMetadata();
117         for (String schema : schemas) {
118             ObjectPartType partMeta = partsMetaMap.get(schema);
119             if (partMeta == null) {
120                 continue; // unknown part, ignore
121             }
122             Map<String, Object> unQObjectProperties = extractPart(docModel, schema, partMeta);
123             addOutputPart(unQObjectProperties, schema, partMeta);
124         }
125     }
126
127     /**
128      * Get the identifier for the transition that sets a document to
129      * the supplied, destination workflow state.
130      *
131      * @param state a destination workflow state.
132      * @return an identifier for the transition required to
133      * place the document in that workflow state.
134      */
135     @Deprecated 
136     private String getTransitionFromState(String state) {
137         String result = TRANSITION_UNKNOWN;
138
139         // FIXME We may wish to add calls, such as those in
140         // org.nuxeo.ecm.core.lifecycle.impl.LifeCycleImpl, to validate incoming
141         // destination workflow state and the set of allowable state transitions.
142
143         if (state.equalsIgnoreCase(WorkflowClient.WORKFLOWSTATE_DELETED)) {
144             result = WorkflowClient.WORKFLOWTRANSITION_DELETE;
145         } else if (state.equalsIgnoreCase(WorkflowClient.WORKFLOWSTATE_ACTIVE)) {
146             result = WorkflowClient.WORKFLOWTRANSITION_UNDELETE; //FIXME, could also be transition WORKFLOWTRANSITION_UNLOCK
147         } else if (state.equalsIgnoreCase(WorkflowClient.WORKFLOWSTATE_LOCKED)) {
148             result = WorkflowClient.WORKFLOWTRANSITION_LOCK;
149         } else {
150                 logger.warn("An attempt was made to transition a document to an unknown workflow state = "
151                                 + state);
152         }        
153         
154         return result;
155     }
156     
157     /*
158      * Maps the transition name to handle existing states like "locked" and "deleted".  This allows us to do things like lock "deleted"
159      * records, delete "locked" records, etc.  For example, this code maps the transition name "delete" to "delete_locked" on records in the "locked" state.
160      * As another example, it would map "undelete" to "undelete_locked" for locked records and just "undelete" for records in any other state.
161      * 
162      * Essentially, this mapping allows REST API clients to use the "delete", "undelete", "lock", "unlock", etc transitions on records no matter what
163      * their current state.  Without this mapping, REST API clients would need to calculate this on their own and use the longer forms like:
164      * "delete_locked", "undelete_locked", "lock_deleted", "unlocked_deleted", etc. 
165      */
166     String getQualifiedTransitionName(DocumentWrapper<DocumentModel> wrapDoc, TransitionDef transitionDef) {
167         String result = null;
168         
169         String currentTransitionName = result = transitionDef.getName(); // begin with result set to the current name
170         DocumentModel docModel = wrapDoc.getWrappedObject();
171         Collection<String> allowedTransitionList = docModel.getAllowedStateTransitions();
172         for (String allowedTransitionName:allowedTransitionList) {
173                 if (allowedTransitionName.startsWith(currentTransitionName)) {
174                         result = allowedTransitionName;
175                         break; // we found a mapping
176                 }
177         }
178
179         return result;
180     }
181     
182     /*
183      * Handle Update (PUT)
184      */
185
186     @Override
187     public void fillAllParts(DocumentWrapper<DocumentModel> wrapDoc, Action action) throws Exception {
188         String transitionToFollow = null;
189         
190         DocumentModel docModel = wrapDoc.getWrappedObject();
191         MultipartServiceContext ctx = (MultipartServiceContext) getServiceContext();
192         
193         try {
194                 TransitionDef transitionDef = (TransitionDef)this.getServiceContext().getProperty(WorkflowClient.TRANSITION_ID);
195                 transitionToFollow = getQualifiedTransitionName(wrapDoc, transitionDef);
196                 docModel.followTransition(transitionToFollow);
197         } catch (Exception e) {
198                 String msg = "Unable to follow workflow transition to state = "
199                                 + transitionToFollow;
200                 logger.error(msg, e);
201                 ClientException ce = new ClientException("Unable to follow workflow transition: " + transitionToFollow);
202                 throw ce;
203         }
204     }    
205 }
206