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     * <p/>
116     * If all attached documents of the workflow instance have been deleted then the workflow is cancelled.
117     *
118     * @param routeId the id of the route instance
119     * @param nodeId the node id to resume on
120     * @param data the data coming from UI form
121     * @param status the status coming from UI form
122     * @param session the session
123     * @since 5.6
124     */
125    void resumeInstance(String routeId, String nodeId, Map<String, Object> data, String status, CoreSession session);
126
127    /**
128     * Completes a task on a give node. If this is the last task the workflow will continue.
129     * <p/>
130     * Called by the UI action corresponding to a task button.
131     *
132     * @param routeId the id of the route instance
133     * @param taskId the id of the task
134     * @param data the data coming from UI form
135     * @param status the status coming from UI form
136     * @param session the session
137     * @since 5.6
138     */
139    void completeTask(String routeId, String taskId, Map<String, Object> data, String status, CoreSession session);
140
141    /**
142     * Save a route instance as a new model of route.
143     * <p/>
144     * The place in which the new instance is persisted and its name depends on {@link DocumentRoutingPersister}. The
145     * route instance should be in either running, done or ready state. The new route model will be in draft state and
146     * won't have any attached documents.
147     *
148     * @param route the instance from which we create a new model.
149     * @return the new model in draft state.
150     */
151    DocumentRoute saveRouteAsNewModel(DocumentRoute route, CoreSession session);
152
153    /**
154     * Return the list of available {@link DocumentRoute} model the user can start.
155     *
156     * @param session The session of the user.
157     * @return A list of available {@link DocumentRoute}
158     */
159    List<DocumentRoute> getAvailableDocumentRouteModel(CoreSession session);
160
161    /**
162     * Return the list of available {@link DocumentRoute} document route.
163     *
164     * @param session The session of the user.
165     * @return A list of available {@link DocumentRoute}
166     * @since 7.2
167     */
168    List<DocumentRoute> getAvailableDocumentRoute(CoreSession session);
169
170    /**
171     * Return the operation chain to run for a documentType. The document type should extend the DocumentRouteStep. Use
172     * the <code>chainsToType</code> extension point to contribute new mapping.
173     *
174     * @deprecated since 5.9.2 - Use only routes of type 'graph'
175     * @param documentType The document type
176     * @return The operation chain id.
177     */
178    @Deprecated
179    String getOperationChainId(String documentType);
180
181    /**
182     * Return the operation chain to undo a step when the step is in running state. The document type should extend the
183     * DocumentRouteStep. Use the <code>chainsToType</code> extension point to contribute new mapping.
184     *
185     * @deprecated since 5.9.2 - Use only routes of type 'graph'
186     * @param documentType
187     * @return
188     */
189    @Deprecated
190    String getUndoFromRunningOperationChainId(String documentType);
191
192    /**
193     * Return the operation chain to undo a step when the step is in done state. The document type should extend the
194     * DocumentRouteStep. Use the <code>chainsToType</code> extension point to contribute new mapping.
195     *
196     * @param documentType
197     * @return
198     */
199    String getUndoFromDoneOperationChainId(String documentType);
200
201    /**
202     * Validates the given {@link DocumentRoute} model by changing its lifecycle state and setting it and all its
203     * children in ReadOnly.
204     *
205     * @return The validated route.
206     */
207    DocumentRoute validateRouteModel(DocumentRoute routeModel, CoreSession session)
208            throws DocumentRouteNotLockedException;
209
210    /**
211     * Unlock the given {@link DocumentRoute} model under unrestricted session.
212     *
213     * @param routeModel
214     * @param userSession
215     * @return The unlocked route.
216     * @since 1.9
217     */
218    public DocumentRoute unlockDocumentRouteUnrestrictedSession(final DocumentRoute routeModel, CoreSession userSession);
219
220    /**
221     * Computes the list of elements {@link DocumentRouteTableElement} for this {@link DocumentRoute}.
222     *
223     * @param routeDocument {@link DocumentRoute}.
224     * @param session The session used to query the {@link DocumentRoute}.
225     * @param A list of {@link DocumentRouteElement}
226     */
227    List<DocumentRouteTableElement> getRouteElements(DocumentRoute route, CoreSession session);
228
229    /**
230     * Return the list of related {@link DocumentRoute} in a state for a given attached document.
231     *
232     * @param session The session used to query the {@link DocumentRoute}.
233     * @param states the list of states.
234     * @return A list of available {@link DocumentRoute}
235     */
236    List<DocumentRoute> getDocumentRoutesForAttachedDocument(CoreSession session, String attachedDocId,
237            List<DocumentRouteElement.ElementLifeCycleState> states);
238
239    /**
240     * @param session
241     * @param attachedDocId
242     * @return
243     * @see #getDocumentRoutesForAttachedDocument(CoreSession, String, List) for route running or ready.
244     */
245    List<DocumentRoute> getDocumentRoutesForAttachedDocument(CoreSession session, String attachedDocId);
246
247    /**
248     * if the user can validate a route.
249     *
250     * @deprecated use {@link #canValidateRoute(DocumentModel, CoreSession)} instead.
251     */
252    @Deprecated
253    boolean canUserValidateRoute(NuxeoPrincipal currentUser);
254
255    /**
256     * Checks if the principal that created the client session can validate the route
257     *
258     * @param documentRoute
259     * @param coreSession
260     */
261    boolean canValidateRoute(DocumentModel documentRoute, CoreSession coreSession);
262
263    /**
264     * Add a route element in another route element.
265     *
266     * @deprecated since 5.9.2 - Use only routes of type 'graph'
267     * @param parentDocumentRef The DocumentRef of the parent document.
268     * @param idx The position of the document in its container.
269     * @param routeElement The document to add.
270     * @param session
271     */
272    @Deprecated
273    void addRouteElementToRoute(DocumentRef parentDocumentRef, int idx, DocumentRouteElement routeElement,
274            CoreSession session) throws DocumentRouteNotLockedException;
275
276    /**
277     * Add a route element in another route element.
278     * <p/>
279     * If the parent element is in draft state, the routeElement is kept in draft state. Otherwise, the element is set
280     * to 'ready' state.
281     *
282     * @deprecated since 5.9.2 - Use only routes of type 'graph'
283     * @param parentDocumentRef The DocumentRef of the parent document.
284     * @param sourceName the name of the previous document in the container.
285     * @param routeElement the document to add.
286     * @param session
287     */
288    @Deprecated
289    void addRouteElementToRoute(DocumentRef parentDocumentRef, String sourceName, DocumentRouteElement routeElement,
290            CoreSession session) throws DocumentRouteNotLockedException;
291
292    /**
293     * Remove the given route element
294     *
295     * @deprecated since 5.9.2 - Use only routes of type 'graph'
296     * @param The route element document.
297     * @param session
298     */
299    @Deprecated
300    void removeRouteElement(DocumentRouteElement routeElement, CoreSession session)
301            throws DocumentRouteNotLockedException;
302
303    /**
304     * Get the children of the given stepFolder ordered by the ecm:pos metadata.
305     *
306     * @deprecated since 5.9.2 - Use only routes of type 'graph'
307     * @param stepFolderId
308     * @param session
309     * @return
310     */
311    @Deprecated
312    DocumentModelList getOrderedRouteElement(String routeElementId, CoreSession session);
313
314    /**
315     * Locks this {@link DocumentRoute} if not already locked by the current user. If the document is already locked by
316     * another user and {@link DocumentRouteAlredayLockedException} is thrown
317     *
318     * @param routeDocument {@link DocumentRoute}.
319     * @param session The session used to lock the {@link DocumentRoute}.
320     * @throws {@link DocumentRouteAlredayLockedException}
321     */
322    void lockDocumentRoute(DocumentRoute routeModel, CoreSession session) throws DocumentRouteAlredayLockedException;
323
324    /**
325     * Unlocks this {@link DocumentRoute}.If the document is not locked throws a {@link DocumentRouteNotLockedException}
326     *
327     * @param routeDocument {@link DocumentRoute}.
328     * @param session The session used to lock the {@link DocumentRoute}.
329     */
330    void unlockDocumentRoute(DocumentRoute routeModel, CoreSession session) throws DocumentRouteNotLockedException;
331
332    /**
333     * Update the given route element
334     *
335     * @param The route element document.
336     * @param session
337     */
338    void updateRouteElement(DocumentRouteElement routeModel, CoreSession session)
339            throws DocumentRouteNotLockedException;
340
341    /**
342     * Verify is this {@link DocumentRoute} is already locked by the current user.
343     *
344     * @param routeDocument {@link DocumentRoute}.
345     * @param session
346     */
347    boolean isLockedByCurrentUser(DocumentRoute routeModel, CoreSession session);
348
349    /**
350     * Checks if the given document can be associated to a DocumentRoute.
351     *
352     * @param doc the document
353     * @return {@code true} if the document can be routed
354     */
355    boolean isRoutable(DocumentModel doc);
356
357    /**
358     * Imports all the route models resource templates.
359     *
360     * @param session the core session to use
361     *
362     * @since 7.3
363     */
364    void importAllRouteModels(CoreSession session);
365
366    /**
367     * Creates a route model in the root models folder defined by the current persister. The templateResource is a zip
368     * tree xml export of a route document and it is imported using the core-io importer.
369     *
370     * @param templateResource
371     * @param overwrite
372     * @param session
373     * @since 5.6
374     */
375    DocumentRoute importRouteModel(URL templateResource, boolean overwrite, CoreSession session);
376
377    /**
378     * Registers a new route model template to be imported at application startup.
379     *
380     * @param resource the resource
381     * @since 5.6
382     */
383    void registerRouteResource(RouteModelResourceType resource, RuntimeContext extensionContext);
384
385    /**
386     * Returns all the route models resource templates. Use the <code>routeModelImporter</code> extension point to
387     * contribute new resources.
388     *
389     * @since 5.6
390     */
391    List<URL> getRouteModelTemplateResources();
392
393    /**
394     * Returns the route models matching the {@code searchString}.
395     *
396     * @since 5.6
397     */
398    List<DocumentModel> searchRouteModels(CoreSession session, String searchString);
399
400    /**
401     * Returns the route model with the given id
402     *
403     * @since 5.6
404     */
405    DocumentRoute getRouteModelWithId(CoreSession session, String id);
406
407    // copied from the deprecated RoutingTaskService
408
409    /**
410     * Returns the doc id of the route model with the given id
411     *
412     * @since 5.7
413     */
414    String getRouteModelDocIdWithId(CoreSession session, String id);
415
416    /**
417     * Marks the tasks as Routing tasks.
418     * <p>
419     * This allows the related documents to be adapted to {@link RoutingTask}.
420     *
421     * @param session the session
422     * @param tasks the tasks
423     * @since 5.6, was on RoutingTaskService before
424     *
425     * @deprecated The facet RoutingTask is statically attached to the new
426     *             RoutingTask Document type since 7.1
427     */
428    @Deprecated
429    void makeRoutingTasks(CoreSession session, List<Task> tasks);
430
431    /**
432     * Ends a task. If this is the last task the workflow will continue.
433     *
434     * @param session
435     * @param task
436     * @param data
437     * @param status name of the button clicked to submit the task form
438     * @since 5.6, was on RoutingTaskService before
439     */
440    void endTask(CoreSession session, Task task, Map<String, Object> data, String status);
441
442    /**
443     * Grants on these documents the specified assignees permissions for this task.
444     *
445     * @param session the session
446     * @param permission the permission
447     * @param docs the documents
448     * @param task the task
449     * @since 5.6
450     */
451    void grantPermissionToTaskAssignees(CoreSession session, String permission, List<DocumentModel> docs, Task task);
452
453    /**
454     * Removes on these documents the specified assignees permissions for this task.
455     *
456     * @param session the session
457     * @param docs the documents
458     * @param task the task
459     * @since 5.6
460     */
461    void removePermissionFromTaskAssignees(CoreSession session, List<DocumentModel> docs, Task task);
462
463    /**
464     * Gets the documents following the workflow to which the given task belongs
465     *
466     * @param session
467     * @param task
468     * @return
469     * @since 5.6, was on RoutingTaskService before
470     */
471    List<DocumentModel> getWorkflowInputDocuments(CoreSession session, Task task);
472
473    /**
474     * Finishes an open task. All permissions granted to the tasks assignees on the document following the worklflow are
475     * removed. Doesn't resume the workflow as the <code>completeTask</code> method. Not executed using an unrestricted
476     * session.
477     *
478     * @param session
479     * @param route
480     * @param task
481     * @param delete
482     * @throws DocumentRouteException
483     * @since 5.7
484     * @deprecated // will be removed in 5.8, use completeTask instead
485     */
486    void finishTask(CoreSession session, DocumentRoute route, Task task, boolean delete) throws DocumentRouteException;
487
488    /**
489     * Cancels an open task. If the task was created by an workflow, all permissions granted to the tasks assignees on
490     * the document following the worklflow are removed. Doesn't resume the workflow as the <code>completeTask</code>
491     * method.
492     *
493     * @param session
494     * @param task
495     * @param delete
496     * @throws DocumentRouteException
497     * @since 5.7.3
498     */
499    void cancelTask(CoreSession session, String taskId) throws DocumentRouteException;
500
501    /**
502     * Reassigns the given task to the list of actors. Removes the permissions granted on the document following the
503     * workflow to the current task assignees and grants them to the new actors.
504     *
505     * @param session
506     * @param taskId
507     * @param actors
508     * @param comment
509     * @since 5.7.3
510     */
511    void reassignTask(CoreSession session, String taskId, List<String> actors, String comment)
512            throws DocumentRouteException;
513
514    /**
515     * Reassigns the given task to the list of actors. Grants to new delegated actors the same permissions as the task
516     * assignees on the document following the workflow .
517     *
518     * @param session
519     * @param taskId
520     * @param delegatedActors
521     * @param comment
522     * @since 5.8
523     */
524    void delegateTask(CoreSession session, String taskId, List<String> delegatedActors, String comment)
525            throws DocumentRouteException;
526
527    /**
528     * Grants on these documents the specified assignees permissions for this task to the tasks delegated actors.
529     *
530     * @param session the session
531     * @param permission the permission
532     * @param docs the documents
533     * @param task the task
534     * @since 5.8
535     */
536    void grantPermissionToTaskDelegatedActors(CoreSession session, String permission, List<DocumentModel> docs,
537            Task task);
538
539    /**
540     * Removes on these documents the specified assignees permissions for the task actors and also tasks delegated
541     * actors if this task was delegated
542     *
543     * @param session the session
544     * @param docs the documents
545     * @param task the task
546     * @since 5.8
547     */
548    void removePermissionsForTaskActors(CoreSession session, List<DocumentModel> docs, Task task);
549
550    /**
551     * Removes on these documents the specified assignees permissions for the task actors and also tasks delegated
552     * actors if this task was delegated
553     *
554     * @param session the session
555     * @param docs the documents
556     * @param taskId the taskId
557     * @since 7.4
558     */
559    void removePermissionsForTaskActors(CoreSession session, List<DocumentModel> docs, String taskId);
560
561    /**
562     * Query for the routes 'done' or 'canceled' and delete them. The max no of the routes that will be deleted is
563     * specified by the 'limit' parameter. When the limit is '0' all the completed routes are deleted. The routes to be
564     * deleted are ordered ascending by their creation date.
565     *
566     * @since 5.8
567     */
568    void cleanupDoneAndCanceledRouteInstances(String repositoryName, int limit);
569
570    /**
571     * @since 5.9.3
572     */
573    void invalidateRouteModelsCache();
574
575    /**
576     * Query for the routes 'done' or 'canceled' and delete them. The max no of the routes that will be deleted is
577     * specified by the 'limit' parameter. When the limit is '0' all the completed routes are deleted. The routes to be
578     * deleted are ordered ascending by their creation date.
579     *
580     * @return the number of cleaned up workflow instance
581     * @since 7.1
582     */
583    int doCleanupDoneAndCanceledRouteInstances(String reprositoryName, int limit);
584
585    /**
586     * @param userId
587     * @param workflowInstanceId
588     * @param session
589     * @return
590     * @since 7.2
591     */
592    List<Task> getTasks(final DocumentModel document, String actorId, String workflowInstanceId,
593            String workflowModelName, CoreSession session);
594
595    /**
596     * @param document
597     * @param session
598     * @return
599     * @since 7.2
600     */
601    List<DocumentRoute> getDocumentRelatedWorkflows(final DocumentModel document, final CoreSession session);
602
603    /**
604     * @since 7.2
605     */
606    List<DocumentRoute> getRunningWorkflowInstancesLaunchedByCurrentUser(final CoreSession session);
607
608    /**
609     * @since 7.2
610     */
611    List<DocumentRoute> getRunningWorkflowInstancesLaunchedByCurrentUser(CoreSession session, String worflowModelName);
612
613    /**
614     * Returns true id the document route is a model, false if it is just an instance i.e. a running workflow.
615     *
616     * @since 7.2
617     */
618    boolean isWorkflowModel(final DocumentRoute documentRoute);
619
620}