package com.joshlong.activiti.coordinator.misc; /* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //package org.activiti.engine.impl.bpmn; import org.activiti.engine.impl.el.Expression; import org.activiti.engine.impl.pvm.PvmTransition; import org.activiti.engine.impl.pvm.delegate.ActivityBehavior; import org.activiti.engine.impl.pvm.delegate.ActivityExecution; import org.activiti.engine.impl.pvm.process.ActivityImpl; import org.activiti.engine.impl.pvm.process.TransitionImpl; import org.activiti.engine.impl.pvm.runtime.ExecutionImpl; import org.activiti.engine.impl.pvm.runtime.OutgoingExecution; import java.util.*; /** * * todo make the iterator variable survive execution * @author Joram Barrez * @since devoxx 2010 * */ public class ForEachActivity implements ActivityBehavior { protected Expression collectionVariableName; protected Expression iteratorVariable; public void execute(ActivityExecution execution) throws Exception { Collection collection = (Collection) execution.getVariable((String) collectionVariableName.getValue(execution)); ActivityImpl activity = (ActivityImpl) execution.getActivity(); TransitionImpl transition = (TransitionImpl) activity.getOutgoingTransitions().get(0); Map<TransitionImpl, Object> transitionVariableMap = new HashMap<TransitionImpl, Object>(); for (Object object : collection) { TransitionImpl newTransition = activity.createOutgoingTransition(); newTransition.setDestination(transition.getDestination()); transitionVariableMap.put(newTransition, object); } takeAll((ExecutionImpl)execution, transitionVariableMap); } // UGLY!!: just copied takeAll for ExecutionImpl: public void takeAll(ExecutionImpl rootExecution ,Map<TransitionImpl, Object> transitionVariableMap) { List<PvmTransition> transitions = new ArrayList<PvmTransition>(transitionVariableMap.keySet()); ExecutionImpl concurrentRoot = ((rootExecution.isConcurrent() && !rootExecution.isScope()) ? rootExecution.getParent() : rootExecution); List<ExecutionImpl> concurrentActiveExecutions = new ArrayList<ExecutionImpl>(); for (ExecutionImpl execution: concurrentRoot.getExecutions()) { if (execution.isActive()) { concurrentActiveExecutions.add(execution); } } if ( (transitions.size()==1) && (concurrentActiveExecutions.isEmpty()) ) { concurrentRoot.setActive(true); concurrentRoot.setActivity(rootExecution.getActivity()); concurrentRoot.setConcurrent(false); concurrentRoot.take(transitions.get(0)); } else { List<OutgoingExecution> outgoingExecutions = new ArrayList<OutgoingExecution>(); // first create the concurrent executions while (!transitions.isEmpty()) { PvmTransition outgoingTransition = transitions.remove(0); ExecutionImpl outgoingExecution = concurrentRoot.createExecution(); outgoingExecution.setActive(true); outgoingExecution.setScope(false); outgoingExecution.setConcurrent(true); outgoingExecutions.add(new OutgoingExecution(outgoingExecution, outgoingTransition, true)); outgoingExecution.setVariable((String) iteratorVariable.getValue(rootExecution), transitionVariableMap.get(outgoingTransition)); } // then launch all the concurrent executions for (OutgoingExecution outgoingExecution: outgoingExecutions) { outgoingExecution.take(); } } } }