/* 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.behavior; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.logging.Logger; import org.activiti.engine.impl.persistence.entity.ExecutionEntity; import org.activiti.engine.impl.pvm.PvmTransition; import org.activiti.engine.impl.pvm.delegate.ActivityExecution; import org.activiti.engine.impl.pvm.process.ActivityImpl; /** * @author Joram Barrez */ public class BoundaryEventActivityBehavior extends FlowNodeActivityBehavior { private static Logger log = Logger.getLogger(BoundaryEventActivityBehavior.class.getName()); protected boolean interrupting; protected String activityId; public BoundaryEventActivityBehavior() { } public BoundaryEventActivityBehavior(boolean interrupting, String activityId) { this.interrupting = interrupting; this.activityId = activityId; } @SuppressWarnings("unchecked") public void execute(ActivityExecution execution) throws Exception { ExecutionEntity executionEntity = (ExecutionEntity) execution; ActivityImpl boundaryActivity = executionEntity.getProcessDefinition().findActivity(activityId); ActivityImpl interruptedActivity = executionEntity.getActivity(); executionEntity.setActivity(boundaryActivity); List<PvmTransition> outgoingTransitions = boundaryActivity.getOutgoingTransitions(); List<ExecutionEntity> interruptedExecutions = null; if (interrupting) { if (executionEntity.getSubProcessInstance()!=null) { executionEntity.getSubProcessInstance().deleteCascade(executionEntity.getDeleteReason()); } interruptedExecutions = new ArrayList<ExecutionEntity>(executionEntity.getExecutions()); for (ExecutionEntity interruptedExecution: interruptedExecutions) { interruptedExecution.deleteCascade("interrupting boundary event '"+execution.getActivity().getId()+"' fired"); } execution.takeAll(outgoingTransitions, (List) interruptedExecutions); } else { // non interrupting event, introduced with BPMN 2.0, we need to create a new execution in this case // create a new execution and move it out from the timer activity ExecutionEntity concurrentRoot = executionEntity.getParent().isConcurrent() ? executionEntity.getParent() : executionEntity; ExecutionEntity outgoingExecution = concurrentRoot.createExecution(); outgoingExecution.setActive(true); outgoingExecution.setScope(false); outgoingExecution.setConcurrent(true); outgoingExecution.takeAll(outgoingTransitions, Collections.EMPTY_LIST); outgoingExecution.remove(); // now we have to move the execution back to the real activity // since the execution stays there (non interrupting) and it was // set to the boundary event before executionEntity.setActivity(interruptedActivity); } } public boolean isInterrupting() { return interrupting; } public void setInterrupting(boolean interrupting) { this.interrupting = interrupting; } }