org.jbpm.simulation.handler.GatewayElementHandler Maven / Gradle / Ivy
/*
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* 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.jbpm.simulation.handler;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;
import org.eclipse.bpmn2.ExclusiveGateway;
import org.eclipse.bpmn2.FlowElement;
import org.eclipse.bpmn2.InclusiveGateway;
import org.eclipse.bpmn2.ParallelGateway;
import org.eclipse.bpmn2.SequenceFlow;
import org.jbpm.simulation.PathContext;
import org.jbpm.simulation.PathContext.Type;
import org.jbpm.simulation.PathContextManager;
public class GatewayElementHandler extends MainElementHandler {
private PathContextManager manager;
public boolean handle(FlowElement element, PathContextManager manager) {
this.manager = manager;
if (element instanceof ExclusiveGateway) {
handleExclusiveGateway(getOutgoing(element));
return true;
} else if (element instanceof InclusiveGateway) {
handleInclusiveGateway(getOutgoing(element));
return true;
} else if (element instanceof ParallelGateway) {
handleParallelGateway(getOutgoing(element));
return true;
} else {
throw new UnsupportedOperationException("Not supported element to handle " + element.eClass().getName());
}
}
protected void handleExclusiveGateway(List outgoing) {
List locked = new ArrayList();
Stack contextsAtThisNode = manager.getContextsFromStack();
for (PathContext contextAtThisNode : contextsAtThisNode) {
for (SequenceFlow seqFlow : outgoing) {
FlowElement target = seqFlow.getTargetRef();
if (!contextAtThisNode.getVisitedSplitPoint().contains(seqFlow)) {
PathContext separatePath = manager.cloneGiven(contextAtThisNode);
separatePath.addVisitedSplitPoint(seqFlow);
manager.addToPath(seqFlow, separatePath);
super.handle(target, manager);
separatePath.setLocked(true);
locked.add(separatePath);
}
}
}
// unlock
for (PathContext ctx : locked) {
ctx.setLocked(false);
}
}
protected void handleInclusiveGateway(List outgoing) {
// firstly cover simple xor based - number of paths is equal to number
// of outgoing
handleExclusiveGateway(outgoing);
Type currentType = manager.getContextFromStack().getType();
manager.getContextFromStack().setType(Type.ROOT);
// next cover all combinations of paths
if (outgoing.size() > 2) {
List copy = new ArrayList(outgoing);
List andCombination = null;
for (SequenceFlow flow : outgoing) {
// first remove one that we currently processing as that is not
// a combination
copy.remove(flow);
PathContext contextAtThisNode = manager.cloneGivenWithoutPush(manager.getContextFromStack());
for (SequenceFlow copyFlow : copy) {
manager.cloneGiven(contextAtThisNode);
andCombination = new ArrayList();
andCombination.add(flow);
andCombination.add(copyFlow);
handleParallelGateway(andCombination);
}
}
}
manager.getContextFromStack().setType(Type.ROOT);
// lastly cover and based - is single path that goes through all at the
// same time
handleParallelGateway(outgoing);
manager.getContextFromStack().setType(currentType);
}
protected void handleParallelGateway(List outgoing) {
PathContext context = manager.getContextFromStack();
boolean canBeFinished = context.isCanBeFinished();
context.setCanBeFinished(false);
manager.addAllToPath(outgoing, context);
int counter = 0;
for (SequenceFlow seqFlow : outgoing) {
counter++;
FlowElement target = seqFlow.getTargetRef();
if (counter == outgoing.size()) {
if (manager.getPaths().size() == 1) {
context.setCanBeFinished(canBeFinished);
} else {
Iterator it = manager.getPaths().iterator();
while (it.hasNext()) {
PathContext pathContext = (PathContext) it.next();
if (pathContext.getType() == Type.ACTIVE) {
pathContext.setCanBeFinished(canBeFinished);
}
}
}
}
super.handle(target, manager);
}
// finalize paths if there are any to cover scenario when there was not converging parallel gateway
if (canBeFinished) {
for (SequenceFlow seqFlow : outgoing) {
manager.addToPath(seqFlow, context);
manager.addToPath(seqFlow.getTargetRef(), context);
}
manager.finalizePathOnLeave();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy