001/*
002 * (C) Copyright 2011 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 */
018package org.nuxeo.ecm.platform.task.core.service;
019
020import java.util.ArrayList;
021import java.util.Collections;
022import java.util.Date;
023import java.util.HashMap;
024import java.util.List;
025import java.util.Map;
026
027import org.apache.commons.lang.StringUtils;
028import org.nuxeo.ecm.core.api.CoreSession;
029import org.nuxeo.ecm.core.api.DocumentModel;
030import org.nuxeo.ecm.core.api.NuxeoException;
031import org.nuxeo.ecm.core.api.NuxeoPrincipal;
032import org.nuxeo.ecm.core.api.UnrestrictedSessionRunner;
033import org.nuxeo.ecm.core.api.security.ACE;
034import org.nuxeo.ecm.core.api.security.ACL;
035import org.nuxeo.ecm.core.api.security.ACP;
036import org.nuxeo.ecm.core.api.security.SecurityConstants;
037import org.nuxeo.ecm.platform.ec.notification.NotificationConstants;
038import org.nuxeo.ecm.platform.task.Task;
039import org.nuxeo.ecm.platform.task.TaskConstants;
040import org.nuxeo.ecm.platform.task.TaskService;
041
042/**
043 * @since 5.5
044 */
045public class CreateTaskUnrestricted extends UnrestrictedSessionRunner {
046
047    private NuxeoPrincipal principal;
048
049    private DocumentModel document;
050
051    private String taskName;
052
053    /**
054     * @since 5.6
055     */
056    private String taskType;
057
058    /**
059     * @since 5.6
060     */
061    private String processId;
062
063    /**
064     * @since 5.6
065     */
066    private String taskDocumentType;
067
068    private List<String> prefixedActorIds;
069
070    private boolean createOneTaskPerActor;
071
072    private String directive;
073
074    private String comment;
075
076    private Date dueDate;
077
078    private Map<String, String> taskVariables;
079
080    private String parentPath;
081
082    /**
083     * @since 7.4
084     */
085    private String processName;
086
087    List<Task> tasks = new ArrayList<Task>();
088
089    /**
090     * @since 5.8 A task can have many target documents
091     */
092    protected List<DocumentModel> documents;
093
094    public CreateTaskUnrestricted(CoreSession session, NuxeoPrincipal principal, DocumentModel document,
095            String taskName, List<String> prefixedActorIds, boolean createOneTaskPerActor, String directive,
096            String comment, Date dueDate, Map<String, String> taskVariables, String parentPath) {
097        this(session, principal, document, taskName, null, null, prefixedActorIds, createOneTaskPerActor, directive,
098                comment, dueDate, taskVariables, parentPath);
099    }
100
101    /**
102     * @since 5.6
103     */
104    public CreateTaskUnrestricted(CoreSession session, NuxeoPrincipal principal, DocumentModel document,
105            String taskName, String taskType, String processId, List<String> prefixedActorIds,
106            boolean createOneTaskPerActor, String directive, String comment, Date dueDate,
107            Map<String, String> taskVariables, String parentPath) {
108        super(session);
109        this.principal = principal;
110        this.document = document;
111        this.taskName = taskName;
112        this.taskType = taskType;
113        this.processId = processId;
114        this.prefixedActorIds = prefixedActorIds;
115        this.createOneTaskPerActor = createOneTaskPerActor;
116        this.directive = directive;
117        this.comment = comment;
118        this.dueDate = dueDate;
119        this.taskVariables = taskVariables;
120        this.parentPath = parentPath;
121        this.documents = new ArrayList<DocumentModel>();
122        this.documents.add(document);
123    }
124
125    /**
126     * @since 5.6
127     */
128    public CreateTaskUnrestricted(CoreSession session, NuxeoPrincipal principal, DocumentModel document,
129            String taskDocumentType, String taskName, String taskType, String processId, List<String> prefixedActorIds,
130            boolean createOneTaskPerActor, String directive, String comment, Date dueDate,
131            Map<String, String> taskVariables, String parentPath) {
132        this(session, principal, document, taskName, taskType, processId, prefixedActorIds, createOneTaskPerActor,
133                directive, comment, dueDate, taskVariables, parentPath);
134        this.taskDocumentType = taskDocumentType;
135    }
136
137    /**
138     * @since 5.8
139     */
140    public CreateTaskUnrestricted(CoreSession session, NuxeoPrincipal principal, List<DocumentModel> documents,
141            String taskDocumentType, String taskName, String taskType, String processId, List<String> prefixedActorIds,
142            boolean createOneTaskPerActor, String directive, String comment, Date dueDate,
143            Map<String, String> taskVariables, String parentPath) {
144        this(session, principal, documents != null && documents.size() > 0 ? documents.get(0) : null, taskName,
145                taskType, processId, prefixedActorIds, createOneTaskPerActor, directive, comment, dueDate,
146                taskVariables, parentPath);
147        this.taskDocumentType = taskDocumentType;
148        this.documents = documents;
149        if (this.documents != null && this.documents.size() > 0) {
150            this.document = documents.get(0);
151        }
152    }
153
154    /**
155     * @since 7.4
156     */
157    public CreateTaskUnrestricted(CoreSession session, NuxeoPrincipal principal, List<DocumentModel> documents,
158            String taskDocumentType, String taskName, String taskType, String processId, String processName, List<String> prefixedActorIds,
159            boolean createOneTaskPerActor, String directive, String comment, Date dueDate,
160            Map<String, String> taskVariables, String parentPath) {
161        this(session, principal, documents != null && documents.size() > 0 ? documents.get(0) : null, taskName,
162                taskType, processId, prefixedActorIds, createOneTaskPerActor, directive, comment, dueDate,
163                taskVariables, parentPath);
164        this.taskDocumentType = taskDocumentType;
165        this.documents = documents;
166        this.processName = processName;
167        if (this.documents != null && this.documents.size() > 0) {
168            this.document = documents.get(0);
169        }
170    }
171
172    @Override
173    public void run() {
174        if (StringUtils.isEmpty(taskDocumentType)) {
175            taskDocumentType = TaskConstants.TASK_TYPE_NAME;
176        }
177        createTask(session, principal, documents, taskDocumentType, taskName, taskType, processId, processName, prefixedActorIds,
178                createOneTaskPerActor, directive, comment, dueDate, taskVariables, parentPath);
179    }
180
181    /**
182     * @since 5.6
183     */
184    public void createTask(CoreSession coreSession, NuxeoPrincipal principal, DocumentModel document,
185            String taskDocumentType, String taskName, String taskType, String processId, List<String> prefixedActorIds,
186            boolean createOneTaskPerActor, String directive, String comment, Date dueDate,
187            Map<String, String> taskVariables, String parentPath) {
188        List<DocumentModel> docs = new ArrayList<DocumentModel>();
189        docs.add(document);
190        createTask(coreSession, principal, docs, taskDocumentType, taskName, taskType, processId, prefixedActorIds,
191                createOneTaskPerActor, directive, comment, dueDate, taskVariables, parentPath);
192
193    }
194
195    /**
196     * @since 5.8
197     */
198    public void createTask(CoreSession coreSession, NuxeoPrincipal principal, List<DocumentModel> documents,
199            String taskDocumentType, String taskName, String taskType, String processId, List<String> prefixedActorIds,
200            boolean createOneTaskPerActor, String directive, String comment, Date dueDate,
201            Map<String, String> taskVariables, String parentPath) {
202        createTask(coreSession, principal, documents, taskDocumentType, taskName, taskType, processId, null,
203                prefixedActorIds, createOneTaskPerActor, directive, comment, dueDate, taskVariables, parentPath);
204    }
205
206    /**
207     * @since 7.4
208     */
209    public void createTask(CoreSession coreSession, NuxeoPrincipal principal, List<DocumentModel> documents,
210            String taskDocumentType, String taskName, String taskType, String processId, String processName, List<String> prefixedActorIds,
211            boolean createOneTaskPerActor, String directive, String comment, Date dueDate,
212            Map<String, String> taskVariables, String parentPath) {
213        if (createOneTaskPerActor) {
214            for (String prefixedActorId : prefixedActorIds) {
215                createTask(coreSession, principal, documents, taskDocumentType, taskName, taskType, processId,
216                        Collections.singletonList(prefixedActorId), false, directive, comment, dueDate, taskVariables,
217                        parentPath);
218            }
219        } else {
220            // use task type as a docName (is actually the nodeId so it
221            // doesn't contain "/" characters), but fallback on task name
222            // if task type is null (for old API kept for compat)
223            String docName = taskType == null ? taskName : taskType;
224            DocumentModel taskDocument = session.createDocumentModel(parentPath, docName, taskDocumentType);
225            Task task = taskDocument.getAdapter(Task.class);
226            if (task == null) {
227                throw new NuxeoException("Document " + taskDocumentType + "  can not be adapted to a Task");
228            }
229            task.setName(taskName);
230            task.setType(taskType);
231            task.setProcessId(processId);
232            task.setProcessName(processName);
233            task.setCreated(new Date());
234            if (principal != null) {
235                String username = principal.getActingUser();
236                task.setInitiator(username);
237            }
238            task.setActors(prefixedActorIds);
239            task.setDueDate(dueDate);
240
241            if (documents != null) {
242                List<String> docIds = new ArrayList<String>();
243                for (DocumentModel doc : documents) {
244                    docIds.add(doc.getId());
245                }
246                task.setTargetDocumentsIds(docIds);
247            }
248            task.setDirective(directive);
249
250            if (!StringUtils.isEmpty(comment)) {
251                task.addComment(principal.getName(), comment);
252            }
253
254            // add variables
255            Map<String, String> variables = new HashMap<String, String>();
256            if (document != null) {
257                variables.put(TaskService.VariableName.documentId.name(), document.getId());
258                variables.put(TaskService.VariableName.documentRepositoryName.name(), document.getRepositoryName());
259            }
260            variables.put(TaskService.VariableName.directive.name(), directive);
261            variables.put(TaskService.VariableName.createdFromTaskService.name(), "true");
262            if (taskVariables != null) {
263                variables.putAll(taskVariables);
264            }
265            task.setVariables(variables);
266
267            // create document in order to set its ACP
268            taskDocument = session.createDocument(taskDocument);
269
270            // re-fetch task from task document to set its id
271            task = taskDocument.getAdapter(Task.class);
272
273            // Set rights
274            List<String> actorIds = new ArrayList<String>();
275            for (String actor : prefixedActorIds) {
276                if (actor.startsWith(NotificationConstants.GROUP_PREFIX)
277                        || actor.startsWith(NotificationConstants.USER_PREFIX)) {
278                    // prefixed assignees with "user:" or "group:"
279                    actorIds.add(actor.substring(actor.indexOf(":") + 1));
280                } else {
281                    actorIds.add(actor);
282                }
283            }
284            ACP acp = taskDocument.getACP();
285            ACL acl = acp.getOrCreateACL(ACL.LOCAL_ACL);
286            if (principal != null) {
287                acl.add(new ACE(principal.getName(), SecurityConstants.EVERYTHING, true));
288
289            }
290            for (String actorId : actorIds) {
291                acl.add(new ACE(actorId, SecurityConstants.EVERYTHING, true));
292            }
293            acp.addACL(acl);
294            taskDocument.setACP(acp, true);
295            taskDocument = session.saveDocument(taskDocument);
296            tasks.add(task);
297        }
298    }
299
300    public void createTask(CoreSession coreSession, NuxeoPrincipal principal, DocumentModel document, String taskName,
301            List<String> prefixedActorIds, boolean createOneTaskPerActor, String directive, String comment,
302            Date dueDate, Map<String, String> taskVariables, String parentPath) {
303        createTask(coreSession, principal, document, TaskConstants.TASK_TYPE_NAME, taskName, null, null,
304                prefixedActorIds, createOneTaskPerActor, directive, comment, dueDate, taskVariables, parentPath);
305    }
306
307    public List<Task> getTasks() {
308        return tasks;
309    }
310
311}