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.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.lang3.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 = { 063 "Workflow.CreateTask" }) 064public class CreateTask { 065 066 public static final String ID = "Task.Create"; 067 068 private static final Log log = LogFactory.getLog(CreateTask.class); 069 070 public enum OperationTaskVariableName { 071 acceptOperationChain, rejectOperationChain, createdFromCreateTaskOperation, taskDocument 072 } 073 074 @Context 075 protected OperationContext ctx; 076 077 @Context 078 protected CoreSession coreSession; 079 080 @Context 081 protected TaskService TaskService; 082 083 @Param(name = "task name", required = true, order = 0) 084 protected String taskName; 085 086 @Param(name = "due date", required = false, order = 1) 087 protected Date dueDate; 088 089 @Param(name = "directive", required = false, order = 2) 090 protected String directive; 091 092 @Param(name = "comment", required = false, order = 3) 093 protected String comment; 094 095 @Param(name = "accept operation chain", required = false, order = 4) 096 protected String acceptOperationChain; 097 098 @Param(name = "reject operation chain", required = false, order = 5) 099 protected String rejectOperationChain; 100 101 @Param(name = "variable name for actors prefixed ids", required = false, order = 6) 102 protected String keyForActors; 103 104 @Param(name = "additional list of actors prefixed ids", required = false, order = 7) 105 protected StringList additionalPrefixedActors; 106 107 @Param(name = "create one task per actor", required = false, values = "true", order = 8) 108 protected boolean createOneTaskPerActor = true; 109 110 @OperationMethod(collector = DocumentModelCollector.class) 111 @SuppressWarnings("unchecked") 112 public DocumentModel run(DocumentModel document) throws OperationException { 113 Principal pal = coreSession.getPrincipal(); 114 if (!(pal instanceof NuxeoPrincipal)) { 115 throw new OperationException("Principal is not an instance of NuxeoPrincipal"); 116 } 117 118 List<String> prefixedActorIds = new ArrayList<>(); 119 Object actors = ctx.get(keyForActors); 120 if (actors != null) { 121 boolean throwError = false; 122 try { 123 if (actors instanceof List) { 124 prefixedActorIds.addAll((List<String>) actors); 125 } else if (actors instanceof String[]) { 126 for (String actor : (String[]) actors) { 127 prefixedActorIds.add(actor); 128 } 129 } else if (actors instanceof String) { 130 prefixedActorIds.add((String) actors); 131 } else { 132 throwError = true; 133 } 134 } catch (ClassCastException e) { 135 throwError = true; 136 } 137 if (throwError) { 138 throw new OperationException(String.format("Invalid key to retrieve a list, array or single " 139 + "string of prefixed actor " + "ids '%s', value is not correct: %s", keyForActors, actors)); 140 } 141 } 142 143 if (additionalPrefixedActors != null) { 144 prefixedActorIds.addAll(additionalPrefixedActors); 145 } 146 147 if (prefixedActorIds.isEmpty()) { 148 // no actors: do nothing 149 log.debug("No actors could be resolved => do not create any task"); 150 return document; 151 } 152 153 // create the task, passing operation chains in task variables 154 Map<String, String> taskVariables = new HashMap<>(); 155 taskVariables.put(OperationTaskVariableName.createdFromCreateTaskOperation.name(), "true"); 156 if (!StringUtils.isEmpty(acceptOperationChain)) { 157 taskVariables.put(OperationTaskVariableName.acceptOperationChain.name(), acceptOperationChain); 158 } 159 if (!StringUtils.isEmpty(rejectOperationChain)) { 160 taskVariables.put(OperationTaskVariableName.rejectOperationChain.name(), rejectOperationChain); 161 } 162 163 // disable notification service 164 taskVariables.put(TaskEventNames.DISABLE_NOTIFICATION_SERVICE, "true"); 165 166 if (TaskService == null) { 167 throw new OperationException("Service jbpmTaskService not found"); 168 } 169 TaskService.createTask(coreSession, (NuxeoPrincipal) pal, document, taskName, prefixedActorIds, 170 createOneTaskPerActor, directive, comment, dueDate, taskVariables, null); 171 172 coreSession.save(); 173 174 return document; 175 } 176 177}