package sushi.application.pages.simulator.model; import java.util.ArrayList; import java.util.List; import org.antlr.grammar.v3.ANTLRParser.finallyClause_return; import sushi.bpmn.decomposition.ANDComponent; import sushi.bpmn.decomposition.Component; import sushi.bpmn.decomposition.LoopComponent; import sushi.bpmn.decomposition.SequenceComponent; import sushi.bpmn.decomposition.XORComponent; import sushi.bpmn.element.AbstractBPMNElement; import sushi.bpmn.element.BPMNAndGateway; import sushi.bpmn.element.BPMNEndEvent; import sushi.bpmn.element.BPMNProcess; import sushi.bpmn.element.BPMNStartEvent; import sushi.bpmn.element.BPMNTask; import sushi.bpmn.element.BPMNXORGateway; import sushi.bpmn.monitoringpoint.MonitoringPoint; import sushi.bpmn.monitoringpoint.MonitoringPointStateTransition; import sushi.event.SushiEventType; import sushi.event.collection.SushiTree; import sushi.util.Tuple; /** * This class converts a tree from the simple simulation page to a BPMN model for the simulator. * @author micha */ public class SimulationTreeTableToModelConverter { SushiTree<Object> tree; BPMNProcess process = new BPMNProcess(); SushiTree<AbstractBPMNElement> bpmnTree = new SushiTree<AbstractBPMNElement>(); int IDCounter = 0; public BPMNProcess convertTreeToModel(SushiTree<Object> tree){ this.tree = tree; BPMNStartEvent startEvent = new BPMNStartEvent(createID(), "Start", null); process.addBPMNElement(startEvent); BPMNEndEvent endEvent = new BPMNEndEvent(createID(), "End", null); process.addBPMNElement(endEvent); convertTreeToBPMNTree(); //Annahme, dass Tree immer mit einer Component (Sequence, XOR, AND oder LOOP) beginnt Tuple<AbstractBPMNElement, AbstractBPMNElement> subStartAndEnd = createSubBranch(bpmnTree.getRootElements().get(0)); AbstractBPMNElement.connectElements(startEvent, subStartAndEnd.x); AbstractBPMNElement.connectElements(subStartAndEnd.y, endEvent); return process; } /** * Tries to create the whole subbrach recursively starting with the given branchStartElement. * @param branchStartElement * @return a list with the start and end element of the created branch */ private Tuple<AbstractBPMNElement, AbstractBPMNElement> createSubBranch(AbstractBPMNElement branchStartElement) { if(branchStartElement instanceof Component){ if(branchStartElement instanceof SequenceComponent){ return createSequenceSubBranch((SequenceComponent)branchStartElement); } else if(branchStartElement instanceof ANDComponent){ return createAndSubBranch((ANDComponent)branchStartElement); } else if(branchStartElement instanceof XORComponent){ return createXORSubBranch((XORComponent)branchStartElement); } else if(branchStartElement instanceof LoopComponent){ return createLoopSubBranch((LoopComponent)branchStartElement); } } BPMNTask task = (BPMNTask) branchStartElement; process.addBPMNElement(task); return(new Tuple<AbstractBPMNElement, AbstractBPMNElement>(task, task)); } private Tuple<AbstractBPMNElement, AbstractBPMNElement> createSequenceSubBranch(SequenceComponent branchStartElement) { List<AbstractBPMNElement> children = bpmnTree.getChildren(branchStartElement); AbstractBPMNElement firstElement = null; AbstractBPMNElement predecessor = null; for(int i = 0; i < children.size(); i++){ Tuple<AbstractBPMNElement, AbstractBPMNElement> subStartAndEnd = createSubBranch(children.get(i)); if(i == 0){ // erstes Element firstElement = (subStartAndEnd.x); } else { //Elemente dazwischen AbstractBPMNElement.connectElements(predecessor, subStartAndEnd.x); } predecessor = subStartAndEnd.y; } //letztes Element der letzten Subkomponente ist gleichzeitig letztes Element der Sequenz return new Tuple<AbstractBPMNElement, AbstractBPMNElement>(firstElement, predecessor); } private Tuple<AbstractBPMNElement, AbstractBPMNElement> createAndSubBranch(ANDComponent branchStartElement) { String ID = createID(); BPMNAndGateway startGateway = new BPMNAndGateway(ID , "AND" + ID, null); process.addBPMNElement(startGateway); ID = createID(); BPMNAndGateway endGateway = new BPMNAndGateway(ID , "AND" + ID, null); process.addBPMNElement(endGateway); //alle Unterelemente erstellen und mit Gateways verbinden for(AbstractBPMNElement child : bpmnTree.getChildren(branchStartElement)){ Tuple<AbstractBPMNElement, AbstractBPMNElement> subStartAndEnd = createSubBranch(child); AbstractBPMNElement.connectElements(startGateway, subStartAndEnd.x); AbstractBPMNElement.connectElements(subStartAndEnd.y, endGateway); } return new Tuple<AbstractBPMNElement, AbstractBPMNElement>(startGateway, endGateway); } private Tuple<AbstractBPMNElement, AbstractBPMNElement> createXORSubBranch(XORComponent branchStartElement) { String ID = createID(); BPMNXORGateway startGateway = new BPMNXORGateway(ID, "XOR" + ID, null); process.addBPMNElement(startGateway); ID = createID(); BPMNXORGateway endGateway = new BPMNXORGateway(ID, "XOR" + ID, null); process.addBPMNElement(endGateway); for(AbstractBPMNElement child : bpmnTree.getChildren(branchStartElement)){ Tuple<AbstractBPMNElement, AbstractBPMNElement> subStartAndEnd = createSubBranch(child); AbstractBPMNElement.connectElements(startGateway, subStartAndEnd.x); AbstractBPMNElement.connectElements(subStartAndEnd.y, endGateway); } return new Tuple<AbstractBPMNElement, AbstractBPMNElement>(startGateway, endGateway); } private Tuple<AbstractBPMNElement, AbstractBPMNElement> createLoopSubBranch(LoopComponent branchStartElement) { List<AbstractBPMNElement> children = bpmnTree.getChildren(branchStartElement); String ID = createID(); BPMNXORGateway startGateway = new BPMNXORGateway(ID, "XOR" + ID, null); process.addBPMNElement(startGateway); ID = createID(); BPMNXORGateway endGateway = new BPMNXORGateway(ID, "XOR" + ID, null); process.addBPMNElement(endGateway); //Schleife einbauen AbstractBPMNElement.connectElements(endGateway, startGateway); AbstractBPMNElement predecessor = startGateway; for(int i = 0; i < children.size(); i++){ Tuple<AbstractBPMNElement, AbstractBPMNElement> subStartAndEnd = createSubBranch(children.get(i)); AbstractBPMNElement.connectElements(predecessor, subStartAndEnd.x); if(i == children.size() - 1){ //letztes Element AbstractBPMNElement.connectElements(subStartAndEnd.y, endGateway); } predecessor = subStartAndEnd.y; } return new Tuple<AbstractBPMNElement, AbstractBPMNElement>(startGateway, endGateway); } /** * Converts the tree of eventTypes and IPattern objects to BPMNTasks and gateway components. */ private void convertTreeToBPMNTree() { for(Object treeElement : tree.getRootElements()){ convertAndAddElementToBPMNTree(treeElement, null); } } private void convertAndAddElementToBPMNTree(Object treeElement, AbstractBPMNElement bpmnParent) { if(treeElement instanceof SushiEventType){ String ID = Integer.toString(++IDCounter); MonitoringPoint monitoringPoint = new MonitoringPoint((SushiEventType) treeElement, MonitoringPointStateTransition.terminate, ""); ArrayList<MonitoringPoint> monitoringPoints = new ArrayList<MonitoringPoint>(); monitoringPoints.add(monitoringPoint); BPMNTask task = new BPMNTask(ID, "Task " + ID, monitoringPoints); bpmnTree.addChild(bpmnParent, task); } else if(treeElement instanceof Component){ if(tree.hasChildren(treeElement)){ AbstractBPMNElement bpmnElement = null; if(treeElement instanceof ANDComponent){ bpmnElement = (ANDComponent) treeElement; } else if(treeElement instanceof XORComponent){ bpmnElement = (XORComponent) treeElement; } else if(treeElement instanceof LoopComponent){ bpmnElement = (LoopComponent) treeElement; } else if(treeElement instanceof SequenceComponent){ bpmnElement = (SequenceComponent) treeElement; } bpmnTree.addChild(bpmnParent, bpmnElement); for(Object child : tree.getChildren(treeElement)){ convertAndAddElementToBPMNTree(child, bpmnElement); } } } } private String createID(){ IDCounter++; return Integer.toString(IDCounter); } }