001/*
002 * (C) Copyright 2009-2012 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Alexandre Russel
018 *     Florent Guillaume
019 */
020package org.nuxeo.ecm.platform.routing.api;
021
022import java.io.Serializable;
023import java.net.URL;
024import java.util.List;
025import java.util.Map;
026
027import org.nuxeo.ecm.core.api.CoreSession;
028import org.nuxeo.ecm.core.api.DocumentModel;
029import org.nuxeo.ecm.core.api.DocumentModelList;
030import org.nuxeo.ecm.core.api.DocumentRef;
031import org.nuxeo.ecm.core.api.NuxeoPrincipal;
032import org.nuxeo.ecm.platform.routing.api.exception.DocumentRouteAlredayLockedException;
033import org.nuxeo.ecm.platform.routing.api.exception.DocumentRouteException;
034import org.nuxeo.ecm.platform.routing.api.exception.DocumentRouteNotLockedException;
035import org.nuxeo.ecm.platform.task.Task;
036import org.nuxeo.runtime.model.RuntimeContext;
037
038/**
039 * The DocumentRoutingService allows manipulation of {@link DocumentRoute DocumentRoutes}.
040 */
041public interface DocumentRoutingService {
042
043    /**
044     * Creates a new route instance and optionally starts it.
045     * <p>
046     * If {@code startInstance = false}, then the route can be started later by calling {@link #startInstance}.
047     *
048     * @param routeModelId the route model id
049     * @param docIds the list of document bound to the instance
050     * @param map the values to pass as initial workflow variables
051     * @param session the session
052     * @param startInstance if the route is automatically started
053     * @return the created route instance id
054     */
055    String createNewInstance(String routeModelId, List<String> docIds, Map<String, Serializable> map,
056            CoreSession session, boolean startInstance);
057
058    /**
059     * Creates a new route instance and optionally starts it.
060     * <p>
061     * If {@code startInstance = false}, then the route can be started later by calling {@link #startInstance}.
062     *
063     * @param routeModelId the route model id
064     * @param docIds The list of document bound to the instance.
065     * @param session the session
066     * @param startInstance if the route is automatically started
067     * @return the created route instance id
068     */
069    String createNewInstance(String routeModelId, List<String> docIds, CoreSession session, boolean startInstance);
070
071    /**
072     * Create a new {@link DocumentRoute} instance from this {@link DocumentRoute} model.
073     *
074     * @param model The model used to create the instance.
075     * @param documentIds The list of document bound to the instance.
076     * @param startInstance if the {@link DocumentRoute} is automatically started.
077     * @return the created {@link DocumentRoute} instance.
078     */
079    DocumentRoute createNewInstance(DocumentRoute model, List<String> documentIds, CoreSession session,
080            boolean startInstance);
081
082    /**
083     * @deprecated since 5.6, use other APIs
084     */
085    @Deprecated
086    DocumentRoute createNewInstance(DocumentRoute model, String documentId, CoreSession session, boolean startInstance);
087
088    /**
089     * @deprecated since 5.6, use other APIs
090     */
091    @Deprecated
092    DocumentRoute createNewInstance(DocumentRoute model, List<String> documentIds, CoreSession session);
093
094    /**
095     * @deprecated since 5.6, use other APIs
096     */
097    @Deprecated
098    DocumentRoute createNewInstance(DocumentRoute model, String documentId, CoreSession session);
099
100    /**
101     * Starts an instance that was created with {@link #createNewInstance} but with {@code startInstance = false}.
102     *
103     * @param routeInstanceId the route instance id
104     * @param docIds the list of document bound to the instance
105     * @param map the values to pass as initial workflow variables
106     * @param session the session
107     * @since 5.7.2
108     */
109    void startInstance(String routeInstanceId, List<String> docIds, Map<String, Serializable> map, CoreSession session);
110
111    /**
112     * Resumes a route instance on a give node. Any remaining tasks on this node will be cancelled.
113     * <p/>
114     * Called by the UI action corresponding to a task button.
115     *
116     * @param routeId the id of the route instance
117     * @param nodeId the node id to resume on
118     * @param data the data coming from UI form
119     * @param status the status coming from UI form
120     * @param session the session
121     * @since 5.6
122     */
123    void resumeInstance(String routeId, String nodeId, Map<String, Object> data, String status, CoreSession session);
124
125    /**
126     * Completes a task on a give node. If this is the last task the workflow will continue.
127     * <p/>
128     * Called by the UI action corresponding to a task button.
129     *
130     * @param routeId the id of the route instance
131     * @param taskId the id of the task
132     * @param data the data coming from UI form
133     * @param status the status coming from UI form
134     * @param session the session
135     * @since 5.6
136     */
137    void completeTask(String routeId, String taskId, Map<String, Object> data, String status, CoreSession session);
138
139    /**
140     * Save a route instance as a new model of route.
141     * <p/>
142     * The place in which the new instance is persisted and its name depends on {@link DocumentRoutingPersister}. The
143     * route instance should be in either running, done or ready state. The new route model will be in draft state and
144     * won't have any attached documents.
145     *
146     * @param route the instance from which we create a new model.
147     * @return the new model in draft state.
148     */
149    DocumentRoute saveRouteAsNewModel(DocumentRoute route, CoreSession session);
150
151    /**
152     * Return the list of available {@link DocumentRoute} model the user can start.
153     *
154     * @param session The session of the user.
155     * @return A list of available {@link DocumentRoute}
156     */
157    List<DocumentRoute> getAvailableDocumentRouteModel(CoreSession session);
158
159    /**
160     * Return the list of available {@link DocumentRoute} document route.
161     *
162     * @param session The session of the user.
163     * @return A list of available {@link DocumentRoute}
164     * @since 7.2
165     */
166    List<DocumentRoute> getAvailableDocumentRoute(CoreSession session);
167
168    /**
169     * Return the operation chain to run for a documentType. The document type should extend the DocumentRouteStep. Use
170     * the <code>chainsToType</code> extension point to contribute new mapping.
171     *
172     * @deprecated since 5.9.2 - Use only routes of type 'graph'
173     * @param documentType The document type
174     * @return The operation chain id.
175     */
176    @Deprecated
177    String getOperationChainId(String documentType);
178
179    /**
180     * Return the operation chain to undo a step when the step is in running state. The document type should extend the
181     * DocumentRouteStep. Use the <code>chainsToType</code> extension point to contribute new mapping.
182     *
183     * @deprecated since 5.9.2 - Use only routes of type 'graph'
184     * @param documentType
185     * @return
186     */
187    @Deprecated
188    String getUndoFromRunningOperationChainId(String documentType);
189
190    /**
191     * Return the operation chain to undo a step when the step is in done state. The document type should extend the
192     * DocumentRouteStep. Use the <code>chainsToType</code> extension point to contribute new mapping.
193     *
194     * @param documentType
195     * @return
196     */
197    String getUndoFromDoneOperationChainId(String documentType);
198
199    /**
200     * Validates the given {@link DocumentRoute} model by changing its lifecycle state and setting it and all its
201     * children in ReadOnly.
202     *
203     * @return The validated route.
204     */
205    DocumentRoute validateRouteModel(DocumentRoute routeModel, CoreSession session)
206            throws DocumentRouteNotLockedException;
207
208    /**
209     * Unlock the given {@link DocumentRoute} model under unrestricted session.
210     *
211     * @param routeModel
212     * @param userSession
213     * @return The unlocked route.
214     * @since 1.9
215     */
216    public DocumentRoute unlockDocumentRouteUnrestrictedSession(final DocumentRoute routeModel, CoreSession userSession);
217
218    /**
219     * Computes the list of elements {@link DocumentRouteTableElement} for this {@link DocumentRoute}.
220     *
221     * @param routeDocument {@link DocumentRoute}.
222     * @param session The session used to query the {@link DocumentRoute}.
223     * @param A list of {@link DocumentRouteElement}
224     */
225    List<DocumentRouteTableElement> getRouteElements(DocumentRoute route, CoreSession session);
226
227    /**
228     * Return the list of related {@link DocumentRoute} in a state for a given attached document.
229     *
230     * @param session The session used to query the {@link DocumentRoute}.
231     * @param states the list of states.
232     * @return A list of available {@link DocumentRoute}
233     */
234    List<DocumentRoute> getDocumentRoutesForAttachedDocument(CoreSession session, String attachedDocId,
235            List<DocumentRouteElement.ElementLifeCycleState> states);
236
237    /**
238     * @param session
239     * @param attachedDocId
240     * @return
241     * @see #getDocumentRoutesForAttachedDocument(CoreSession, String, List) for route running or ready.
242     */
243    List<DocumentRoute> getDocumentRoutesForAttachedDocument(CoreSession session, String attachedDocId);
244
245    /**
246     * if the user can validate a route.
247     *
248     * @deprecated use {@link #canValidateRoute(DocumentModel, CoreSession)} instead.
249     */
250    @Deprecated
251    boolean canUserValidateRoute(NuxeoPrincipal currentUser);
252
253    /**
254     * Checks if the principal that created the client session can validate the route
255     *
256     * @param documentRoute
257     * @param coreSession
258     */
259    boolean canValidateRoute(DocumentModel documentRoute, CoreSession coreSession);
260
261    /**
262     * Add a route element in another route element.
263     *
264     * @deprecated since 5.9.2 - Use only routes of type 'graph'
265     * @param parentDocumentRef The DocumentRef of the parent document.
266     * @param idx The position of the document in its container.
267     * @param routeElement The document to add.
268     * @param session
269     */
270    @Deprecated
271    void addRouteElementToRoute(DocumentRef parentDocumentRef, int idx, DocumentRouteElement routeElement,
272            CoreSession session) throws DocumentRouteNotLockedException;
273
274    /**
275     * Add a route element in another route element.
276     * <p/>
277     * If the parent element is in draft state, the routeElement is kept in draft state. Otherwise, the element is set
278     * to 'ready' state.
279     *
280     * @deprecated since 5.9.2 - Use only routes of type 'graph'
281     * @param parentDocumentRef The DocumentRef of the parent document.
282     * @param sourceName the name of the previous document in the container.
283     * @param routeElement the document to add.
284     * @param session
285     */
286    @Deprecated
287    void addRouteElementToRoute(DocumentRef parentDocumentRef, String sourceName, DocumentRouteElement routeElement,
288            CoreSession session) throws DocumentRouteNotLockedException;
289
290    /**
291     * Remove the given route element
292     *
293     * @deprecated since 5.9.2 - Use only routes of type 'graph'
294     * @param The route element document.
295     * @param session
296     */
297    @Deprecated
298    void removeRouteElement(DocumentRouteElement routeElement, CoreSession session)
299            throws DocumentRouteNotLockedException;
300
301    /**
302     * Get the children of the given stepFolder ordered by the ecm:pos metadata.
303     *
304     * @deprecated since 5.9.2 - Use only routes of type 'graph'
305     * @param stepFolderId
306     * @param session
307     * @return
308     */
309    @Deprecated
310    DocumentModelList getOrderedRouteElement(String routeElementId, CoreSession session);
311
312    /**
313     * Locks this {@link DocumentRoute} if not already locked by the current user. If the document is already locked by
314     * another user and {@link DocumentRouteAlredayLockedException} is thrown
315     *
316     * @param routeDocument {@link DocumentRoute}.
317     * @param session The session used to lock the {@link DocumentRoute}.
318     * @throws {@link DocumentRouteAlredayLockedException}
319     */
320    void lockDocumentRoute(DocumentRoute routeModel, CoreSession session) throws DocumentRouteAlredayLockedException;
321
322    /**
323     * Unlocks this {@link DocumentRoute}.If the document is not locked throws a {@link DocumentRouteNotLockedException}
324     *
325     * @param routeDocument {@link DocumentRoute}.
326     * @param session The session used to lock the {@link DocumentRoute}.
327     */
328    void unlockDocumentRoute(DocumentRoute routeModel, CoreSession session) throws DocumentRouteNotLockedException;
329
330    /**
331     * Update the given route element
332     *
333     * @param The route element document.
334     * @param session
335     */
336    void updateRouteElement(DocumentRouteElement routeModel, CoreSession session)
337            throws DocumentRouteNotLockedException;
338
339    /**
340     * Verify is this {@link DocumentRoute} is already locked by the current user.
341     *
342     * @param routeDocument {@link DocumentRoute}.
343     * @param session
344     */
345    boolean isLockedByCurrentUser(DocumentRoute routeModel, CoreSession session);
346
347    /**
348     * Checks if the given document can be associated to a DocumentRoute.
349     *
350     * @param doc the document
351     * @return {@code true} if the document can be routed
352     */
353    boolean isRoutable(DocumentModel doc);
354
355    /**
356     * Imports all the route models resource templates.
357     *
358     * @param session the core session to use
359     *
360     * @since 7.3
361     */
362    void importAllRouteModels(CoreSession session);
363
364    /**
365     * Creates a route model in the root models folder defined by the current persister. The templateResource is a zip
366     * tree xml export of a route document and it is imported using the core-io importer.
367     *
368     * @param templateResource
369     * @param overwrite
370     * @param session
371     * @since 5.6
372     */
373    DocumentRoute importRouteModel(URL templateResource, boolean overwrite, CoreSession session);
374
375    /**
376     * Registers a new route model template to be imported at application startup.
377     *
378     * @param resource the resource
379     * @since 5.6
380     */
381    void registerRouteResource(RouteModelResourceType resource, RuntimeContext extensionContext);
382
383    /**
384     * Returns all the route models resource templates. Use the <code>routeModelImporter</code> extension point to
385     * contribute new resources.
386     *
387     * @since 5.6
388     */
389    List<URL> getRouteModelTemplateResources();
390
391    /**
392     * Returns the route models matching the {@code searchString}.
393     *
394     * @since 5.6
395     */
396    List<DocumentModel> searchRouteModels(CoreSession session, String searchString);
397
398    /**
399     * Returns the route model with the given id
400     *
401     * @since 5.6
402     */
403    DocumentRoute getRouteModelWithId(CoreSession session, String id);
404
405    // copied from the deprecated RoutingTaskService
406
407    /**
408     * Returns the doc id of the route model with the given id
409     *
410     * @since 5.7
411     */
412    String getRouteModelDocIdWithId(CoreSession session, String id);
413
414    /**
415     * Marks the tasks as Routing tasks.
416     * <p>
417     * This allows the related documents to be adapted to {@link RoutingTask}.
418     *
419     * @param session the session
420     * @param tasks the tasks
421     * @since 5.6, was on RoutingTaskService before
422     *
423     * @deprecated The facet RoutingTask is statically attached to the new
424     *             RoutingTask Document type since 7.1
425     */
426    @Deprecated
427    void makeRoutingTasks(CoreSession session, List<Task> tasks);
428
429    /**
430     * Ends a task. If this is the last task the workflow will continue.
431     *
432     * @param session
433     * @param task
434     * @param data
435     * @param status name of the button clicked to submit the task form
436     * @since 5.6, was on RoutingTaskService before
437     */
438    void endTask(CoreSession session, Task task, Map<String, Object> data, String status);
439
440    /**
441     * Grants on these documents the specified assignees permissions for this task.
442     *
443     * @param session the session
444     * @param permission the permission
445     * @param docs the documents
446     * @param task the task
447     * @since 5.6
448     */
449    void grantPermissionToTaskAssignees(CoreSession session, String permission, List<DocumentModel> docs, Task task);
450
451    /**
452     * Removes on these documents the specified assignees permissions for this task.
453     *
454     * @param session the session
455     * @param docs the documents
456     * @param task the task
457     * @since 5.6
458     */
459    void removePermissionFromTaskAssignees(CoreSession session, List<DocumentModel> docs, Task task);
460
461    /**
462     * Gets the documents following the workflow to which the given task belongs
463     *
464     * @param session
465     * @param task
466     * @return
467     * @since 5.6, was on RoutingTaskService before
468     */
469    List<DocumentModel> getWorkflowInputDocuments(CoreSession session, Task task);
470
471    /**
472     * Finishes an open task. All permissions granted to the tasks assignees on the document following the worklflow are
473     * removed. Doesn't resume the workflow as the <code>completeTask</code> method. Not executed using an unrestricted
474     * session.
475     *
476     * @param session
477     * @param route
478     * @param task
479     * @param delete
480     * @throws DocumentRouteException
481     * @since 5.7
482     * @deprecated // will be removed in 5.8, use completeTask instead
483     */
484    void finishTask(CoreSession session, DocumentRoute route, Task task, boolean delete) throws DocumentRouteException;
485
486    /**
487     * Cancels an open task. If the task was created by an workflow, all permissions granted to the tasks assignees on
488     * the document following the worklflow are removed. Doesn't resume the workflow as the <code>completeTask</code>
489     * method.
490     *
491     * @param session
492     * @param task
493     * @param delete
494     * @throws DocumentRouteException
495     * @since 5.7.3
496     */
497    void cancelTask(CoreSession session, String taskId) throws DocumentRouteException;
498
499    /**
500     * Reassigns the given task to the list of actors. Removes the permissions granted on the document following the
501     * workflow to the current task assignees and grants them to the new actors.
502     *
503     * @param session
504     * @param taskId
505     * @param actors
506     * @param comment
507     * @since 5.7.3
508     */
509    void reassignTask(CoreSession session, String taskId, List<String> actors, String comment)
510            throws DocumentRouteException;
511
512    /**
513     * Reassigns the given task to the list of actors. Grants to new delegated actors the same permissions as the task
514     * assignees on the document following the workflow .
515     *
516     * @param session
517     * @param taskId
518     * @param delegatedActors
519     * @param comment
520     * @since 5.8
521     */
522    void delegateTask(CoreSession session, String taskId, List<String> delegatedActors, String comment)
523            throws DocumentRouteException;
524
525    /**
526     * Grants on these documents the specified assignees permissions for this task to the tasks delegated actors.
527     *
528     * @param session the session
529     * @param permission the permission
530     * @param docs the documents
531     * @param task the task
532     * @since 5.8
533     */
534    void grantPermissionToTaskDelegatedActors(CoreSession session, String permission, List<DocumentModel> docs,
535            Task task);
536
537    /**
538     * Removes on these documents the specified assignees permissions for the task actors and also tasks delegated
539     * actors if this task was delegated
540     *
541     * @param session the session
542     * @param docs the documents
543     * @param task the task
544     * @since 5.8
545     */
546    void removePermissionsForTaskActors(CoreSession session, List<DocumentModel> docs, Task task);
547
548    /**
549     * Removes on these documents the specified assignees permissions for the task actors and also tasks delegated
550     * actors if this task was delegated
551     *
552     * @param session the session
553     * @param docs the documents
554     * @param taskId the taskId
555     * @since 7.4
556     */
557    void removePermissionsForTaskActors(CoreSession session, List<DocumentModel> docs, String taskId);
558
559    /**
560     * Query for the routes 'done' or 'canceled' and delete them. The max no of the routes that will be deleted is
561     * specified by the 'limit' parameter. When the limit is '0' all the completed routes are deleted. The routes to be
562     * deleted are ordered ascending by their creation date.
563     *
564     * @since 5.8
565     */
566    void cleanupDoneAndCanceledRouteInstances(String repositoryName, int limit);
567
568    /**
569     * @since 5.9.3
570     */
571    void invalidateRouteModelsCache();
572
573    /**
574     * Query for the routes 'done' or 'canceled' and delete them. The max no of the routes that will be deleted is
575     * specified by the 'limit' parameter. When the limit is '0' all the completed routes are deleted. The routes to be
576     * deleted are ordered ascending by their creation date.
577     *
578     * @return the number of cleaned up workflow instance
579     * @since 7.1
580     */
581    int doCleanupDoneAndCanceledRouteInstances(String reprositoryName, int limit);
582
583    /**
584     * @param userId
585     * @param workflowInstanceId
586     * @param session
587     * @return
588     * @since 7.2
589     */
590    List<Task> getTasks(final DocumentModel document, String actorId, String workflowInstanceId,
591            String workflowModelName, CoreSession session);
592
593    /**
594     * @param document
595     * @param session
596     * @return
597     * @since 7.2
598     */
599    List<DocumentRoute> getDocumentRelatedWorkflows(final DocumentModel document, final CoreSession session);
600
601    /**
602     * @since 7.2
603     */
604    List<DocumentRoute> getRunningWorkflowInstancesLaunchedByCurrentUser(final CoreSession session);
605
606    /**
607     * @since 7.2
608     */
609    List<DocumentRoute> getRunningWorkflowInstancesLaunchedByCurrentUser(CoreSession session, String worflowModelName);
610
611    /**
612     * Returns true id the document route is a model, false if it is just an instance i.e. a running workflow.
613     *
614     * @since 7.2
615     */
616    boolean isWorkflowModel(final DocumentRoute documentRoute);
617
618}