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