/* * JBoss, Home of Professional Open Source * Copyright 2005, JBoss Inc., and individual contributors as indicated * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jbpm.jpdl.internal.activity; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.collections.map.ListOrderedMap; import org.jbpm.api.JbpmException; import org.jbpm.api.ProcessEngine; import org.jbpm.api.TaskQuery; import org.jbpm.api.activity.ActivityBehaviour; import org.jbpm.api.activity.ActivityExecution; import org.jbpm.api.model.OpenExecution; import org.jbpm.api.task.Assignable; import org.jbpm.internal.log.Log; import org.jbpm.properties.JBpm4Properties; import org.jbpm.pvm.internal.env.EnvironmentFactory; import org.jbpm.pvm.internal.env.EnvironmentImpl; import org.jbpm.pvm.internal.history.HistoryEvent; import org.jbpm.pvm.internal.history.events.TaskActivityStart; import org.jbpm.pvm.internal.model.Activity; import org.jbpm.pvm.internal.model.ActivityImpl; import org.jbpm.pvm.internal.model.ExecutionImpl; import org.jbpm.pvm.internal.model.ProcessDefinitionImpl; import org.jbpm.pvm.internal.model.TimerDefinitionImpl; import org.jbpm.pvm.internal.model.Transition; import org.jbpm.pvm.internal.model.TransitionImpl; import org.jbpm.pvm.internal.session.DbSession; import org.jbpm.pvm.internal.task.ParticipationImpl; import org.jbpm.pvm.internal.task.SwimlaneDefinitionImpl; import org.jbpm.pvm.internal.task.SwimlaneImpl; import org.jbpm.pvm.internal.task.TaskConstants; import org.jbpm.pvm.internal.task.TaskDefinitionImpl; import org.jbpm.pvm.internal.task.TaskImpl; /** * @author Tom Baeyens */ public class TaskActivity extends JpdlExternalActivity { private static final long serialVersionUID = 1L; private static final Log log = Log.getLog(TaskActivity.class.getName()); protected TaskDefinitionImpl taskDefinition; private static String className = JBpm4Properties .getStringProperty("jbpm4.engin.checkTaskUser"); private static Object newInstance = null; private static Method method = null; public void execute(ActivityExecution execution) throws Exception { execute((ExecutionImpl) execution); } public void execute(ExecutionImpl execution) throws Exception { DbSession dbSession = EnvironmentImpl.getFromCurrent(DbSession.class); TaskImpl task = (TaskImpl) dbSession.createTask(); task.setTaskDefinition(taskDefinition); task.setExecution(execution); task.setProcessInstance(execution.getProcessInstance()); task.setSignalling(true); // initialize the name if (taskDefinition.getName() != null) { task.setName(taskDefinition.getName()); } else { task.setName(execution.getActivityName()); } task.setDescription(taskDefinition.getDescription()); task.setPriority(taskDefinition.getPriority()); task.setFormResourceName(taskDefinition.getFormResourceName()); // save task so that TaskDbSession.findTaskByExecution works for assign // event listeners dbSession.save(task); SwimlaneDefinitionImpl swimlaneDefinition = taskDefinition .getSwimlaneDefinition(); if (swimlaneDefinition != null) { SwimlaneImpl swimlane = execution .getInitializedSwimlane(swimlaneDefinition); task.setSwimlane(swimlane); // copy the swimlane assignments to the task task.setAssignee(swimlane.getAssignee()); for (ParticipationImpl participant : swimlane.getParticipations()) { task.addParticipation(participant.getUserId(), participant.getGroupId(), participant.getType()); } } if (className != null && !"".equals(className)) { getInstance(); Object invoke = method.invoke(newInstance, execution .getProcessInstance().getId(), task.getName()); int index = 0; if(invoke!=null){ if (invoke instanceof String[]) { String[] invoke2 = (String[]) invoke; if (invoke2.length == 1) { taskDefinition.setAssigneeExpression(invoke2[0]); } else if (invoke2.length > 1) { for (String user : invoke2) { if (index == 0) { this.taskDefinition.setAssigneeExpression(user); } task.addCandidateUser(user); index++; } } } } } execution.initializeAssignments(taskDefinition, task); HistoryEvent.fire(new TaskActivityStart(task), execution); execution.waitForSignal(); } private static void getInstance() throws SecurityException, NoSuchMethodException, ClassNotFoundException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException{ Class cls = Class.forName(className); getMethod(cls); if(newInstance ==null){ newInstance = cls.getConstructor().newInstance(); } } private static void getMethod(Class cls) throws SecurityException, NoSuchMethodException{ if(method==null){ method = cls.getMethod("userList", String.class, String.class); } } public void signal(ActivityExecution execution, String signalName, Map parameters) throws Exception { signal((ExecutionImpl) execution, signalName, parameters); } public void signal(ExecutionImpl execution, String signalName, Map parameters) throws Exception { Activity activity = execution.getActivity(); if (parameters != null) { execution.setVariables(parameters); } execution.fire(signalName, activity); DbSession taskDbSession = EnvironmentImpl .getFromCurrent(DbSession.class); TaskImpl task = (TaskImpl) taskDbSession.findTaskByExecution(execution); task.setSignalling(false); Transition transition = null; List outgoingTransitions = activity .getOutgoingTransitions(); if ((outgoingTransitions != null) && (!outgoingTransitions.isEmpty())) { // Lookup the outgoing transition boolean noOutcomeSpecified = TaskConstants.NO_TASK_OUTCOME_SPECIFIED .equals(signalName); if (noOutcomeSpecified && activity.findOutgoingTransition(signalName) == null) { // When no specific outcome was specified, the unnamed // transition // is looked up (name is null). If a null outcome was // specifically // used, then the else clause will be used (but the result is // the same) // Note: the second part of the if clause is to avoid the // siutation // where the user would have chosen the same name as the // constant transition = activity.findOutgoingTransition(null); } else { transition = activity.findOutgoingTransition(signalName); } // If no transition has been found, we check if we have a special // case // in which we can still deduce the outgoing transition if (transition == null) { // no unnamed transition found if (signalName == null) { // null was explicitely given as outcome throw new JbpmException( "No unnamed transitions were found for the task '" + getTaskDefinition().getName() + "'"); } else if (noOutcomeSpecified) { // Special case: complete(id) if (outgoingTransitions.size() == 1) { // If only 1 // transition, take // that one transition = outgoingTransitions.get(0); } else { throw new JbpmException( "No unnamed transitions were found for the task '" + getTaskDefinition().getName() + "'"); } } else { // Likely a programmatic error. throw new JbpmException("No transition named '" + signalName + "' was found."); } } if (transition != null) { execution.take(transition); } } } /** * Checks if the given collection of transitions are all named or not. */ private boolean allTransitionsNamed(Collection transitions) { for (Transition transition : transitions) { if (transition.getName() == null) { return false; } } return true; } public TaskDefinitionImpl getTaskDefinition() { return taskDefinition; } public void setTaskDefinition(TaskDefinitionImpl taskDefinition) { this.taskDefinition = taskDefinition; } }