001/* 002 * (C) Copyright 2010-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 * Anahide Tchertchian 018 */ 019 020package org.nuxeo.ecm.automation.task; 021 022import java.security.Principal; 023import java.util.ArrayList; 024import java.util.Date; 025import java.util.HashMap; 026import java.util.List; 027import java.util.Map; 028 029import org.apache.commons.lang.StringUtils; 030import org.apache.commons.logging.Log; 031import org.apache.commons.logging.LogFactory; 032import org.nuxeo.ecm.automation.OperationContext; 033import org.nuxeo.ecm.automation.OperationException; 034import org.nuxeo.ecm.automation.core.Constants; 035import org.nuxeo.ecm.automation.core.annotations.Context; 036import org.nuxeo.ecm.automation.core.annotations.Operation; 037import org.nuxeo.ecm.automation.core.annotations.OperationMethod; 038import org.nuxeo.ecm.automation.core.annotations.Param; 039import org.nuxeo.ecm.automation.core.collectors.DocumentModelCollector; 040import org.nuxeo.ecm.automation.core.util.StringList; 041import org.nuxeo.ecm.core.api.CoreSession; 042import org.nuxeo.ecm.core.api.DocumentModel; 043import org.nuxeo.ecm.core.api.NuxeoPrincipal; 044import org.nuxeo.ecm.platform.task.TaskEventNames; 045import org.nuxeo.ecm.platform.task.TaskService; 046 047/** 048 * Creates a task 049 * 050 * @author Anahide Tchertchian 051 * @since 5.5 052 */ 053@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. " 054 + "<p><b>Directive</b>, <b>comment</b> and <b>due date</b> will be displayed in the task list of the user. " 055 + "In <b>accept operation chain</b> and <b>reject operation chain</b> fields, " 056 + "you can put the operation chain ID of your choice among the one you contributed. " 057 + "Those operations will be executed when the user validates the task, " 058 + "depending on whether he accepts or rejects the task. " 059 + "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. " 060 + "You can use Get Users and Groups to update a context variable with some users and groups. " 061 + "If you check <b>create one task per actor</b>, each of the actors will have a task to achieve, " 062 + "versus \"the first who achieve the task makes it disappear for the others\".</p>", aliases = { "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 Principal pal = coreSession.getPrincipal(); 113 if (!(pal instanceof NuxeoPrincipal)) { 114 throw new OperationException("Principal is not an instance of NuxeoPrincipal"); 115 } 116 117 List<String> prefixedActorIds = new ArrayList<String>(); 118 Object actors = ctx.get(keyForActors); 119 if (actors != null) { 120 boolean throwError = false; 121 try { 122 if (actors instanceof List) { 123 prefixedActorIds.addAll((List<String>) actors); 124 } else if (actors instanceof String[]) { 125 for (String actor : (String[]) actors) { 126 prefixedActorIds.add(actor); 127 } 128 } else if (actors instanceof String) { 129 prefixedActorIds.add((String) actors); 130 } else { 131 throwError = true; 132 } 133 } catch (ClassCastException e) { 134 throwError = true; 135 } 136 if (throwError) { 137 throw new OperationException(String.format("Invalid key to retrieve a list, array or single " 138 + "string of prefixed actor " + "ids '%s', value is not correct: %s", keyForActors, actors)); 139 } 140 } 141 142 if (additionalPrefixedActors != null) { 143 prefixedActorIds.addAll(additionalPrefixedActors); 144 } 145 146 if (prefixedActorIds.isEmpty()) { 147 // no actors: do nothing 148 log.debug("No actors could be resolved => do not create any task"); 149 return document; 150 } 151 152 // create the task, passing operation chains in task variables 153 Map<String, String> taskVariables = new HashMap<String, String>(); 154 taskVariables.put(OperationTaskVariableName.createdFromCreateTaskOperation.name(), "true"); 155 if (!StringUtils.isEmpty(acceptOperationChain)) { 156 taskVariables.put(OperationTaskVariableName.acceptOperationChain.name(), acceptOperationChain); 157 } 158 if (!StringUtils.isEmpty(rejectOperationChain)) { 159 taskVariables.put(OperationTaskVariableName.rejectOperationChain.name(), rejectOperationChain); 160 } 161 162 // disable notification service 163 taskVariables.put(TaskEventNames.DISABLE_NOTIFICATION_SERVICE, "true"); 164 165 if (TaskService == null) { 166 throw new OperationException("Service jbpmTaskService not found"); 167 } 168 TaskService.createTask(coreSession, (NuxeoPrincipal) pal, document, taskName, prefixedActorIds, 169 createOneTaskPerActor, directive, comment, dueDate, taskVariables, null); 170 171 coreSession.save(); 172 173 return document; 174 } 175 176}