001/* 002 * (C) Copyright 2010-2018 Nuxeo (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 * Anahide Tchertchian 018 */ 019 020package org.nuxeo.ecm.automation.task; 021 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.lang3.StringUtils; 029import org.apache.commons.logging.Log; 030import org.apache.commons.logging.LogFactory; 031import org.nuxeo.ecm.automation.OperationContext; 032import org.nuxeo.ecm.automation.OperationException; 033import org.nuxeo.ecm.automation.core.Constants; 034import org.nuxeo.ecm.automation.core.annotations.Context; 035import org.nuxeo.ecm.automation.core.annotations.Operation; 036import org.nuxeo.ecm.automation.core.annotations.OperationMethod; 037import org.nuxeo.ecm.automation.core.annotations.Param; 038import org.nuxeo.ecm.automation.core.collectors.DocumentModelCollector; 039import org.nuxeo.ecm.automation.core.util.StringList; 040import org.nuxeo.ecm.core.api.CoreSession; 041import org.nuxeo.ecm.core.api.DocumentModel; 042import org.nuxeo.ecm.core.api.NuxeoPrincipal; 043import org.nuxeo.ecm.platform.task.TaskEventNames; 044import org.nuxeo.ecm.platform.task.TaskService; 045 046/** 047 * Creates a task 048 * 049 * @author Anahide Tchertchian 050 * @since 5.5 051 */ 052@Operation(id = CreateTask.ID, category = Constants.CAT_SERVICES, label = "Create task", since = "5.3.2", description = "Enable to create a task bound to the document. " 053 + "<p><b>Directive</b>, <b>comment</b> and <b>due date</b> will be displayed in the task list of the user. " 054 + "In <b>accept operation chain</b> and <b>reject operation chain</b> fields, " 055 + "you can put the operation chain ID of your choice among the one you contributed. " 056 + "Those operations will be executed when the user validates the task, " 057 + "depending on whether he accepts or rejects the task. " 058 + "You have to specify a variable name (the <b>key for ... </b> parameter) to resolve target users and groups to which the task will be assigned. " 059 + "You can use Get Users and Groups to update a context variable with some users and groups. " 060 + "If you check <b>create one task per actor</b>, each of the actors will have a task to achieve, " 061 + "versus \"the first who achieve the task makes it disappear for the others\".</p>", aliases = { 062 "Workflow.CreateTask" }) 063public class CreateTask { 064 065 public static final String ID = "Task.Create"; 066 067 private static final Log log = LogFactory.getLog(CreateTask.class); 068 069 public enum OperationTaskVariableName { 070 acceptOperationChain, rejectOperationChain, createdFromCreateTaskOperation, taskDocument 071 } 072 073 @Context 074 protected OperationContext ctx; 075 076 @Context 077 protected CoreSession coreSession; 078 079 @Context 080 protected TaskService TaskService; 081 082 @Param(name = "task name", required = true, order = 0) 083 protected String taskName; 084 085 @Param(name = "due date", required = false, order = 1) 086 protected Date dueDate; 087 088 @Param(name = "directive", required = false, order = 2) 089 protected String directive; 090 091 @Param(name = "comment", required = false, order = 3) 092 protected String comment; 093 094 @Param(name = "accept operation chain", required = false, order = 4) 095 protected String acceptOperationChain; 096 097 @Param(name = "reject operation chain", required = false, order = 5) 098 protected String rejectOperationChain; 099 100 @Param(name = "variable name for actors prefixed ids", required = false, order = 6) 101 protected String keyForActors; 102 103 @Param(name = "additional list of actors prefixed ids", required = false, order = 7) 104 protected StringList additionalPrefixedActors; 105 106 @Param(name = "create one task per actor", required = false, values = "true", order = 8) 107 protected boolean createOneTaskPerActor = true; 108 109 @OperationMethod(collector = DocumentModelCollector.class) 110 @SuppressWarnings("unchecked") 111 public DocumentModel run(DocumentModel document) throws OperationException { 112 NuxeoPrincipal pal = coreSession.getPrincipal(); 113 114 List<String> prefixedActorIds = new ArrayList<>(); 115 Object actors = ctx.get(keyForActors); 116 if (actors != null) { 117 boolean throwError = false; 118 try { 119 if (actors instanceof List) { 120 prefixedActorIds.addAll((List<String>) actors); 121 } else if (actors instanceof String[]) { 122 for (String actor : (String[]) actors) { 123 prefixedActorIds.add(actor); 124 } 125 } else if (actors instanceof String) { 126 prefixedActorIds.add((String) actors); 127 } else { 128 throwError = true; 129 } 130 } catch (ClassCastException e) { 131 throwError = true; 132 } 133 if (throwError) { 134 throw new OperationException(String.format("Invalid key to retrieve a list, array or single " 135 + "string of prefixed actor " + "ids '%s', value is not correct: %s", keyForActors, actors)); 136 } 137 } 138 139 if (additionalPrefixedActors != null) { 140 prefixedActorIds.addAll(additionalPrefixedActors); 141 } 142 143 if (prefixedActorIds.isEmpty()) { 144 // no actors: do nothing 145 log.debug("No actors could be resolved => do not create any task"); 146 return document; 147 } 148 149 // create the task, passing operation chains in task variables 150 Map<String, String> taskVariables = new HashMap<>(); 151 taskVariables.put(OperationTaskVariableName.createdFromCreateTaskOperation.name(), "true"); 152 if (!StringUtils.isEmpty(acceptOperationChain)) { 153 taskVariables.put(OperationTaskVariableName.acceptOperationChain.name(), acceptOperationChain); 154 } 155 if (!StringUtils.isEmpty(rejectOperationChain)) { 156 taskVariables.put(OperationTaskVariableName.rejectOperationChain.name(), rejectOperationChain); 157 } 158 159 // disable notification service 160 taskVariables.put(TaskEventNames.DISABLE_NOTIFICATION_SERVICE, "true"); 161 162 if (TaskService == null) { 163 throw new OperationException("Service jbpmTaskService not found"); 164 } 165 TaskService.createTask(coreSession, pal, document, taskName, prefixedActorIds, createOneTaskPerActor, directive, 166 comment, dueDate, taskVariables, null); 167 168 coreSession.save(); 169 170 return document; 171 } 172 173}