001/*
002 * (C) Copyright 2012-2016 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 *     ldoguin, Antoine Taillefer
018 */
019package org.nuxeo.ecm.platform.task.core.service;
020
021import java.io.Serializable;
022import java.util.ArrayList;
023import java.util.Date;
024import java.util.HashMap;
025import java.util.List;
026import java.util.Map;
027
028import org.apache.commons.lang.StringUtils;
029import org.nuxeo.common.utils.Path;
030import org.nuxeo.ecm.core.api.CoreSession;
031import org.nuxeo.ecm.core.api.DocumentModel;
032import org.nuxeo.ecm.core.api.DocumentNotFoundException;
033import org.nuxeo.ecm.core.api.DocumentRef;
034import org.nuxeo.ecm.core.api.IdRef;
035import org.nuxeo.ecm.core.api.NuxeoException;
036import org.nuxeo.ecm.core.api.NuxeoGroup;
037import org.nuxeo.ecm.core.api.NuxeoPrincipal;
038import org.nuxeo.ecm.core.api.PathRef;
039import org.nuxeo.ecm.core.api.SortInfo;
040import org.nuxeo.ecm.core.api.UnrestrictedSessionRunner;
041import org.nuxeo.ecm.core.api.security.ACE;
042import org.nuxeo.ecm.core.api.security.ACL;
043import org.nuxeo.ecm.core.api.security.ACP;
044import org.nuxeo.ecm.core.api.security.SecurityConstants;
045import org.nuxeo.ecm.platform.ec.notification.NotificationConstants;
046import org.nuxeo.ecm.platform.task.Task;
047import org.nuxeo.ecm.platform.task.TaskConstants;
048import org.nuxeo.ecm.platform.task.TaskEventNames;
049import org.nuxeo.ecm.platform.task.TaskPersisterDescriptor;
050import org.nuxeo.ecm.platform.task.TaskProvider;
051import org.nuxeo.ecm.platform.task.TaskProviderDescriptor;
052import org.nuxeo.ecm.platform.task.TaskService;
053import org.nuxeo.runtime.model.ComponentContext;
054import org.nuxeo.runtime.model.ComponentInstance;
055import org.nuxeo.runtime.model.ComponentName;
056import org.nuxeo.runtime.model.DefaultComponent;
057
058/**
059 * @author <a href="mailto:ldoguin@nuxeo.com">Laurent Doguin</a>
060 * @since 5.5
061 */
062public class TaskServiceImpl extends DefaultComponent implements TaskService {
063
064    private static final long serialVersionUID = 1L;
065
066    public static final ComponentName NAME = new ComponentName("org.nuxeo.ecm.platform.task.core.TaskService");
067
068    public static final String DEFAULT_TASK_PROVIDER = "documentTaskProvider";
069
070    private static final String TASK_PROVIDER_XP = "taskProvider";
071
072    private static final String TASK_PERSISTER_XP = "taskPersister";
073
074    private Map<String, TaskProvider> tasksProviders;
075
076    private String parentPath = "/task-root";
077
078    @Override
079    public void activate(ComponentContext context) {
080        super.activate(context);
081        tasksProviders = new HashMap<>();
082    }
083
084    @Override
085    public void deactivate(ComponentContext context) {
086        super.deactivate(context);
087        tasksProviders = null;
088    }
089
090    @Override
091    public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) {
092        if (extensionPoint.equals(TASK_PROVIDER_XP)) {
093            if (contribution instanceof TaskProviderDescriptor) {
094                TaskProviderDescriptor taskProviderDescriptor = (TaskProviderDescriptor) contribution;
095                String providerId = taskProviderDescriptor.getId();
096                if (taskProviderDescriptor.isEnabled()) {
097                    tasksProviders.put(providerId, taskProviderDescriptor.getNewInstance());
098                } else {
099                    if (tasksProviders.get(providerId) != null) {
100                        tasksProviders.remove(providerId);
101                    }
102                }
103            }
104        } else if (extensionPoint.equals(TASK_PERSISTER_XP)) {
105            if (contribution instanceof TaskPersisterDescriptor) {
106                TaskPersisterDescriptor taskPersisterDescriptor = (TaskPersisterDescriptor) contribution;
107                parentPath = taskPersisterDescriptor.getPath();
108            }
109        }
110    }
111
112    @Override
113    public void unregisterContribution(Object contribution, String extensionPoint, ComponentInstance contributor) {
114        if (extensionPoint.equals(TASK_PROVIDER_XP)) {
115            if (contribution instanceof TaskProviderDescriptor) {
116                TaskProviderDescriptor taskProviderDescriptor = (TaskProviderDescriptor) contribution;
117                String providerId = taskProviderDescriptor.getId();
118                if (tasksProviders.get(providerId) != null) {
119                    tasksProviders.remove(providerId);
120                }
121            }
122        }
123    }
124
125    @Override
126    public List<Task> createTask(CoreSession coreSession, NuxeoPrincipal principal, DocumentModel document,
127            String taskName, List<String> actorIds, boolean createOneTaskPerActor, String directive, String comment,
128            Date dueDate, Map<String, String> taskVariables, String parentPath) {
129        return createTask(coreSession, principal, document, taskName, null, null, actorIds, createOneTaskPerActor,
130                directive, comment, dueDate, taskVariables, parentPath);
131    }
132
133    /**
134     * @since 5.6
135     */
136    @Override
137    public List<Task> createTask(CoreSession coreSession, NuxeoPrincipal principal, DocumentModel document,
138            String taskDocumentType, String taskName, String taskType, String processId, List<String> actorIds,
139            boolean createOneTaskPerActor, String directive, String comment, Date dueDate,
140            Map<String, String> taskVariables, String parentPath, Map<String, Serializable> eventInfo) {
141        List<DocumentModel> docs = new ArrayList<>();
142        docs.add(document);
143        return createTaskForProcess(coreSession, principal, docs, taskDocumentType, taskName, taskType, processId, null,
144                actorIds, createOneTaskPerActor, directive, comment, dueDate, taskVariables, parentPath, eventInfo);
145    }
146
147    /**
148     * @since 5.6
149     */
150    @Override
151    public List<Task> createTask(CoreSession coreSession, NuxeoPrincipal principal, DocumentModel document,
152            String taskName, String taskType, String processId, List<String> prefixedActorIds,
153            boolean createOneTaskPerActor, String directive, String comment, Date dueDate,
154            Map<String, String> taskVariables, String parentPath) {
155        return createTask(coreSession, principal, document, TaskConstants.TASK_TYPE_NAME, taskName, taskType, processId,
156                prefixedActorIds, createOneTaskPerActor, directive, comment, dueDate, taskVariables, parentPath, null);
157    }
158
159    @Override
160    public String acceptTask(CoreSession coreSession, NuxeoPrincipal principal, Task task, String comment) {
161        return endTask(coreSession, principal, task, comment, TaskEventNames.WORKFLOW_TASK_COMPLETED, true);
162    }
163
164    @Override
165    public String rejectTask(CoreSession coreSession, NuxeoPrincipal principal, Task task, String comment) {
166        return endTask(coreSession, principal, task, comment, TaskEventNames.WORKFLOW_TASK_REJECTED, false);
167    }
168
169    /**
170     * Use the task provider held by the {@link Task#TASK_PROVIDER_KEY} task variable to end the {@code task}. If null
171     * use the {@link #DEFAULT_TASK_PROVIDER}.
172     */
173    @Override
174    public String endTask(CoreSession coreSession, NuxeoPrincipal principal, Task task, String comment,
175            String eventName, boolean isValidated) {
176
177        if (!canEndTask(principal, task)) {
178            throw new NuxeoException(String.format("User with id '%s' cannot end this task", principal.getName()));
179        }
180        String taskProviderId = task.getVariable(Task.TASK_PROVIDER_KEY);
181        if (taskProviderId == null) {
182            taskProviderId = DEFAULT_TASK_PROVIDER;
183        }
184        TaskProvider taskProvider = tasksProviders.get(taskProviderId);
185        if (taskProvider == null) {
186            throw new NuxeoException(String.format(
187                    "No task provider registered, cannot end task. Please contribute at least the default task provider: %s.",
188                    DEFAULT_TASK_PROVIDER));
189        }
190        return taskProvider.endTask(coreSession, principal, task, comment, eventName, isValidated);
191    }
192
193    @Override
194    public boolean canEndTask(NuxeoPrincipal principal, Task task) {
195        if (task != null && (!task.isCancelled() && !task.hasEnded())) {
196            return principal.isAdministrator() || principal.getName().equals(task.getInitiator())
197                    || isTaskAssignedToUser(task, principal, true);
198        }
199        return false;
200    }
201
202    protected boolean isTaskAssignedToUser(Task task, NuxeoPrincipal user, boolean checkDelegatedActors) {
203        if (task != null && user != null) {
204            // user actors
205            List<String> actors = user.getAllGroups();
206            actors.add(user.getName());
207
208            // initiator
209            if (actors.contains(task.getInitiator())) {
210                return true;
211            }
212            // users
213            List<String> users = task.getActors();
214            if (checkDelegatedActors) {
215                users.addAll(task.getDelegatedActors());
216            }
217            if (users != null) {
218                for (String userName : users) {
219                    if (userName.startsWith(NuxeoPrincipal.PREFIX)) {
220                        if (actors.contains(userName.substring(NuxeoPrincipal.PREFIX.length()))) {
221                            return true;
222                        }
223                    } else if (userName.startsWith(NuxeoGroup.PREFIX)) {
224                        if (actors.contains(userName.substring(NuxeoGroup.PREFIX.length()))) {
225                            return true;
226                        }
227                    } else if (actors.contains(userName)) {
228                        return true;
229                    }
230                }
231            }
232        }
233        return false;
234    }
235
236    @Override
237    public Task getTask(CoreSession coreSession, String taskId) {
238        DocumentRef docRef = new IdRef(taskId);
239        DocumentModel taskDoc = coreSession.getDocument(docRef);
240        if (taskDoc != null) {
241            Task task = taskDoc.getAdapter(Task.class);
242            if (task != null) {
243                return task;
244            }
245        }
246        return null;
247    }
248
249    @Override
250    public void deleteTask(CoreSession coreSession, String taskId) {
251        final DocumentRef docRef = new IdRef(taskId);
252        UnrestrictedSessionRunner runner = new UnrestrictedSessionRunner(coreSession) {
253            @Override
254            public void run() {
255                session.removeDocument(docRef);
256            }
257        };
258        runner.runUnrestricted();
259    }
260
261    @Override
262    public DocumentModel getTargetDocumentModel(Task task, CoreSession coreSession) {
263        try {
264            // TODO handle while target documents from task
265            return coreSession.getDocument(new IdRef(task.getTargetDocumentsIds().get(0)));
266        } catch (DocumentNotFoundException e) {
267            return null;
268        }
269    }
270
271    @Override
272    public List<Task> getCurrentTaskInstances(CoreSession coreSession) {
273        List<Task> tasks = new ArrayList<>();
274        List<Task> newTasks;
275        for (TaskProvider taskProvider : tasksProviders.values()) {
276            newTasks = taskProvider.getCurrentTaskInstances(coreSession);
277            if (newTasks != null) {
278                tasks.addAll(newTasks);
279            }
280        }
281        return tasks;
282    }
283
284    /**
285     * Provide @param sortInfo to handle sort page-provider contributions (see {@link #getCurrentTaskInstances})
286     *
287     * @since 5.9.3
288     */
289    @Override
290    public List<Task> getCurrentTaskInstances(CoreSession coreSession, List<SortInfo> sortInfos) {
291        List<Task> tasks = new ArrayList<>();
292        List<Task> newTasks;
293        for (TaskProvider taskProvider : tasksProviders.values()) {
294            newTasks = taskProvider.getCurrentTaskInstances(coreSession, sortInfos);
295            if (newTasks != null) {
296                tasks.addAll(newTasks);
297            }
298        }
299        return tasks;
300    }
301
302    @Override
303    public List<Task> getAllCurrentTaskInstances(CoreSession coreSession, List<SortInfo> sortInfos) {
304        List<Task> tasks = new ArrayList<>();
305        List<Task> newTasks;
306        for (TaskProvider taskProvider : tasksProviders.values()) {
307            newTasks = taskProvider.getAllCurrentTaskInstances(coreSession, sortInfos);
308            if (newTasks != null) {
309                tasks.addAll(newTasks);
310            }
311        }
312        return tasks;
313    }
314
315    /**
316     * Returns a list of task instances assigned to one of the actors in the list or to its pool.
317     *
318     * @param actors a list used as actorId to retrieve the tasks.
319     */
320    @Override
321    public List<Task> getCurrentTaskInstances(List<String> actors, CoreSession coreSession) {
322        List<Task> tasks = new ArrayList<>();
323        List<Task> newTasks;
324        for (TaskProvider taskProvider : tasksProviders.values()) {
325            newTasks = taskProvider.getCurrentTaskInstances(actors, coreSession);
326            if (newTasks != null) {
327                tasks.addAll(newTasks);
328            }
329        }
330        return tasks;
331    }
332
333    /**
334     * Provide @param sortInfo to handle sort page-provider contributions (see {@link #getCurrentTaskInstances})
335     *
336     * @since 5.9.3
337     */
338    @Override
339    public List<Task> getCurrentTaskInstances(List<String> actors, CoreSession coreSession, List<SortInfo> sortInfos) {
340        List<Task> tasks = new ArrayList<>();
341        List<Task> newTasks;
342        for (TaskProvider taskProvider : tasksProviders.values()) {
343            newTasks = taskProvider.getCurrentTaskInstances(actors, coreSession, sortInfos);
344            if (newTasks != null) {
345                tasks.addAll(newTasks);
346            }
347        }
348        return tasks;
349    }
350
351    @Override
352    public List<Task> getTaskInstances(DocumentModel dm, NuxeoPrincipal user, CoreSession coreSession) {
353        List<Task> tasks = new ArrayList<>();
354        List<Task> newTasks;
355        for (TaskProvider taskProvider : tasksProviders.values()) {
356            newTasks = taskProvider.getTaskInstances(dm, user, coreSession);
357            if (newTasks != null) {
358                tasks.addAll(newTasks);
359            }
360        }
361        return tasks;
362    }
363
364    @Override
365    public List<Task> getTaskInstances(DocumentModel dm, List<String> actors, CoreSession coreSession) {
366        List<Task> tasks = new ArrayList<>();
367        List<Task> newTasks;
368        for (TaskProvider taskProvider : tasksProviders.values()) {
369            newTasks = taskProvider.getTaskInstances(dm, actors, coreSession);
370            if (newTasks != null) {
371                tasks.addAll(newTasks);
372            }
373        }
374        return tasks;
375    }
376
377    @Override
378    public List<Task> getAllTaskInstances(String processId, CoreSession session) {
379        List<Task> tasks = new ArrayList<>();
380        List<Task> newTasks;
381        for (TaskProvider taskProvider : tasksProviders.values()) {
382            newTasks = taskProvider.getAllTaskInstances(processId, session);
383            if (newTasks != null) {
384                tasks.addAll(newTasks);
385            }
386        }
387        return tasks;
388    }
389
390    @Override
391    public List<Task> getAllTaskInstances(String processId, NuxeoPrincipal user, CoreSession session) {
392        List<Task> tasks = new ArrayList<>();
393        List<Task> newTasks;
394        for (TaskProvider taskProvider : tasksProviders.values()) {
395            newTasks = taskProvider.getAllTaskInstances(processId, user, session);
396            if (newTasks != null) {
397                tasks.addAll(newTasks);
398            }
399        }
400        return tasks;
401    }
402
403    @Override
404    public List<Task> getAllTaskInstances(String processId, List<String> actors, CoreSession session) {
405        List<Task> tasks = new ArrayList<>();
406        List<Task> newTasks;
407        for (TaskProvider taskProvider : tasksProviders.values()) {
408            newTasks = taskProvider.getAllTaskInstances(processId, actors, session);
409            if (newTasks != null) {
410                tasks.addAll(newTasks);
411            }
412        }
413        return tasks;
414    }
415
416    @Override
417    public String getTaskRootParentPath(CoreSession coreSession) {
418        GetTaskRootParentPathUnrestricted runner = new GetTaskRootParentPathUnrestricted(coreSession);
419        runner.runUnrestricted();
420        return runner.getParentPath();
421    }
422
423    public class GetTaskRootParentPathUnrestricted extends UnrestrictedSessionRunner {
424
425        protected DocumentModel taskRootDoc;
426
427        public GetTaskRootParentPathUnrestricted(CoreSession session) {
428            super(session);
429        }
430
431        @Override
432        public void run() {
433            DocumentRef pathRef = new PathRef(parentPath);
434            if (session.exists(pathRef)) {
435                taskRootDoc = session.getDocument(pathRef);
436            } else {
437                Path path = new Path(parentPath);
438                taskRootDoc = session.createDocumentModel(path.removeLastSegments(1).toString(), path.lastSegment(),
439                        TaskConstants.TASK_ROOT_TYPE_NAME);
440                taskRootDoc = session.createDocument(taskRootDoc);
441                ACP acp = taskRootDoc.getACP();
442                ACL acl = acp.getOrCreateACL(ACL.LOCAL_ACL);
443                acl.add(new ACE("Everyone", "Everything", false));
444                taskRootDoc.setACP(acp, true);
445                taskRootDoc = session.saveDocument(taskRootDoc);
446            }
447        }
448
449        public DocumentModel getTaskRootDoc() {
450            return taskRootDoc;
451        }
452
453        public String getParentPath() {
454            return taskRootDoc.getPathAsString();
455        }
456    }
457
458    @Override
459    public List<Task> getAllTaskInstances(String processId, String nodeId, CoreSession session) {
460        List<Task> tasks = new ArrayList<>();
461        List<Task> newTasks;
462        for (TaskProvider taskProvider : tasksProviders.values()) {
463            newTasks = taskProvider.getAllTaskInstances(processId, nodeId, session);
464            if (newTasks != null) {
465                tasks.addAll(newTasks);
466            }
467        }
468        return tasks;
469    }
470
471    @Override
472    public void reassignTask(CoreSession session, final String taskId, final List<String> newActors,
473            final String comment) {
474
475        new UnrestrictedSessionRunner(session) {
476
477            @Override
478            public void run() {
479                DocumentModel taskDoc = session.getDocument(new IdRef(taskId));
480                Task task = taskDoc.getAdapter(Task.class);
481                if (task == null) {
482                    throw new NuxeoException("Invalid taskId: " + taskId);
483                }
484                List<String> currentAssignees = task.getActors();
485                List<String> currentActors = new ArrayList<>();
486                for (String currentAssignee : currentAssignees) {
487                    if (currentAssignee.startsWith(NotificationConstants.GROUP_PREFIX)
488                            || currentAssignee.startsWith(NotificationConstants.USER_PREFIX)) {
489                        // prefixed assignees with "user:" or "group:"
490                        currentActors.add(currentAssignee.substring(currentAssignee.indexOf(":") + 1));
491                    } else {
492                        currentActors.add(currentAssignee);
493                    }
494                }
495                String taskInitator = task.getInitiator();
496
497                // remove ACLs set for current assignees
498                ACP acp = taskDoc.getACP();
499                ACL acl = acp.getOrCreateACL(ACL.LOCAL_ACL);
500                List<ACE> toRemove = new ArrayList<>();
501
502                for (ACE ace : acl.getACEs()) {
503                    if (currentActors.contains(ace.getUsername()) || taskInitator.equals(ace.getUsername())) {
504                        toRemove.add(ace);
505                    }
506                }
507                acl.removeAll(toRemove);
508
509                // grant EVERYTHING on task doc to the new actors
510                List<String> actorIds = new ArrayList<>();
511                for (String actor : newActors) {
512                    if (actor.startsWith(NotificationConstants.GROUP_PREFIX)
513                            || actor.startsWith(NotificationConstants.USER_PREFIX)) {
514                        // prefixed assignees with "user:" or "group:"
515                        actorIds.add(actor.substring(actor.indexOf(":") + 1));
516                    } else {
517                        actorIds.add(actor);
518                    }
519                }
520                for (String actorId : actorIds) {
521                    acl.add(new ACE(actorId, SecurityConstants.EVERYTHING, true));
522                }
523
524                taskDoc.setACP(acp, true);
525                task.setActors(actorIds);
526                String currentUser = ((NuxeoPrincipal) session.getPrincipal()).getActingUser();
527                task.addComment(currentUser, comment);
528                session.saveDocument(taskDoc);
529
530                List<DocumentModel> docs = new ArrayList<>();
531                for (String string : task.getTargetDocumentsIds()) {
532                    docs.add(session.getDocument(new IdRef(string)));
533
534                }
535                notifyEvent(session, task, docs, TaskEventNames.WORKFLOW_TASK_REASSIGNED, new HashMap<>(), comment,
536                        (NuxeoPrincipal) session.getPrincipal(), actorIds);
537
538            }
539        }.runUnrestricted();
540
541    }
542
543    @Override
544    public void delegateTask(CoreSession session, final String taskId, final List<String> delegatedActors,
545            final String comment) {
546
547        new UnrestrictedSessionRunner(session) {
548            @Override
549            public void run() {
550                DocumentModel taskDoc = session.getDocument(new IdRef(taskId));
551                Task task = taskDoc.getAdapter(Task.class);
552                if (task == null) {
553                    throw new NuxeoException("Invalid taskId: " + taskId);
554                }
555                // grant EVERYTHING on task doc to the delegated actors
556                List<String> actorIds = new ArrayList<>();
557                ACP acp = taskDoc.getACP();
558                ACL acl = acp.getOrCreateACL(ACL.LOCAL_ACL);
559
560                for (String actor : delegatedActors) {
561                    if (actor.startsWith(NotificationConstants.GROUP_PREFIX)
562                            || actor.startsWith(NotificationConstants.USER_PREFIX)) {
563                        // prefixed assignees with "user:" or "group:"
564                        actorIds.add(actor.substring(actor.indexOf(":") + 1));
565                    } else {
566                        actorIds.add(actor);
567                    }
568                }
569                for (String actorId : actorIds) {
570                    ACE ace = new ACE(actorId, SecurityConstants.EVERYTHING, true);
571                    if (!acl.contains(ace)) {
572                        acl.add(ace);
573                    }
574                }
575                taskDoc.setACP(acp, true);
576
577                List<String> allDelegatedActors = new ArrayList<>();
578                allDelegatedActors.addAll(task.getDelegatedActors());
579                for (String actor : actorIds) {
580                    if (!allDelegatedActors.contains(actor)) {
581                        allDelegatedActors.add(actor);
582                    }
583                }
584                task.setDelegatedActors(allDelegatedActors);
585
586                String currentUser = ((NuxeoPrincipal) session.getPrincipal()).getActingUser();
587                task.addComment(currentUser, comment);
588                session.saveDocument(taskDoc);
589                List<DocumentModel> docs = new ArrayList<>();
590                for (String string : task.getTargetDocumentsIds()) {
591                    docs.add(session.getDocument(new IdRef(string)));
592
593                }
594                notifyEvent(session, task, docs, TaskEventNames.WORKFLOW_TASK_DELEGATED, new HashMap<>(),
595                        String.format("Task delegated by '%s' to '%s'", currentUser, StringUtils.join(actorIds, ","))
596                                + (!StringUtils.isEmpty(comment) ? " with the following comment: " + comment : ""),
597                        (NuxeoPrincipal) session.getPrincipal(), actorIds);
598            }
599
600        }.runUnrestricted();
601    }
602
603    protected void notifyEvent(CoreSession session, Task task, List<DocumentModel> docs, String event,
604            Map<String, Serializable> eventInfo, String comment, NuxeoPrincipal principal, List<String> actorIds) {
605        Map<String, Serializable> eventProperties = new HashMap<>();
606        ArrayList<String> notificationRecipients = new ArrayList<>();
607        notificationRecipients.addAll(actorIds);
608        eventProperties.put(NotificationConstants.RECIPIENTS_KEY,
609                notificationRecipients.toArray(new String[notificationRecipients.size()]));
610        if (eventInfo != null) {
611            eventProperties.putAll(eventInfo);
612        }
613        for (DocumentModel doc : docs) {
614            TaskEventNotificationHelper.notifyEvent(session, doc, principal, task, event, eventProperties, comment,
615                    null);
616        }
617    }
618
619    @Override
620    public List<Task> getTaskInstances(DocumentModel dm, List<String> actors, boolean includeDelegatedTasks,
621            CoreSession session) {
622        List<Task> tasks = new ArrayList<>();
623        for (TaskProvider taskProvider : tasksProviders.values()) {
624            tasks.addAll(taskProvider.getTaskInstances(dm, actors, includeDelegatedTasks, session));
625        }
626        return tasks;
627    }
628
629    /**
630     * @since 5.8
631     * @deprecated since 7.4 use
632     *             {@link #createTaskForProcess(CoreSession, NuxeoPrincipal, List, String, String, String, String, String, List, boolean, String, String, Date, Map, String, Map)}
633     *             instead
634     */
635    @Override
636    @Deprecated
637    public List<Task> createTask(CoreSession coreSession, NuxeoPrincipal principal, List<DocumentModel> documents,
638            String taskDocumentType, String taskName, String taskType, String processId, List<String> actorIds,
639            boolean createOneTaskPerActor, String directive, String comment, Date dueDate,
640            Map<String, String> taskVariables, String parentPath, Map<String, Serializable> eventInfo) {
641        return createTaskForProcess(coreSession, principal, documents, taskDocumentType, taskName, taskType, processId,
642                null, actorIds, createOneTaskPerActor, directive, comment, dueDate, taskVariables, parentPath,
643                eventInfo);
644    }
645
646    /**
647     * @since 7.4
648     */
649    @Override
650    public List<Task> createTaskForProcess(CoreSession coreSession, NuxeoPrincipal principal,
651            List<DocumentModel> documents, String taskDocumentType, String taskName, String taskType, String processId,
652            String processName, List<String> actorIds, boolean createOneTaskPerActor, String directive, String comment,
653            Date dueDate, Map<String, String> taskVariables, String parentPath, Map<String, Serializable> eventInfo) {
654        if (StringUtils.isBlank(parentPath)) {
655            parentPath = getTaskRootParentPath(coreSession);
656        }
657        CreateTaskUnrestricted runner = new CreateTaskUnrestricted(coreSession, principal, documents, taskDocumentType,
658                taskName, taskType, processId, processName, actorIds, createOneTaskPerActor, directive, comment,
659                dueDate, taskVariables, parentPath);
660        runner.runUnrestricted();
661
662        List<Task> tasks = runner.getTasks();
663
664        for (Task task : tasks) {
665            // notify
666            notifyEvent(coreSession, task, documents, TaskEventNames.WORKFLOW_TASK_ASSIGNED, eventInfo, comment,
667                    principal, task.getActors());
668        }
669        return tasks;
670    }
671}