/* 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.designer.eclipse.bpmnimport;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import org.activiti.designer.eclipse.bpmn.BpmnParser;
import org.activiti.designer.eclipse.bpmn.GraphicInfo;
import org.activiti.designer.eclipse.bpmn.SequenceFlowModel;
import org.activiti.designer.eclipse.preferences.PreferencesUtil;
import org.activiti.designer.util.preferences.Preferences;
import org.apache.commons.lang.StringUtils;
import org.eclipse.bpmn2.Activity;
import org.eclipse.bpmn2.BoundaryEvent;
import org.eclipse.bpmn2.Bpmn2Factory;
import org.eclipse.bpmn2.BusinessRuleTask;
import org.eclipse.bpmn2.CallActivity;
import org.eclipse.bpmn2.CandidateGroup;
import org.eclipse.bpmn2.CandidateUser;
import org.eclipse.bpmn2.Documentation;
import org.eclipse.bpmn2.EndEvent;
import org.eclipse.bpmn2.ErrorEventDefinition;
import org.eclipse.bpmn2.Event;
import org.eclipse.bpmn2.EventDefinition;
import org.eclipse.bpmn2.ExclusiveGateway;
import org.eclipse.bpmn2.FieldExtension;
import org.eclipse.bpmn2.FlowElement;
import org.eclipse.bpmn2.FlowNode;
import org.eclipse.bpmn2.Gateway;
import org.eclipse.bpmn2.InclusiveGateway;
import org.eclipse.bpmn2.MailTask;
import org.eclipse.bpmn2.ManualTask;
import org.eclipse.bpmn2.ParallelGateway;
import org.eclipse.bpmn2.ReceiveTask;
import org.eclipse.bpmn2.ScriptTask;
import org.eclipse.bpmn2.SequenceFlow;
import org.eclipse.bpmn2.ServiceTask;
import org.eclipse.bpmn2.StartEvent;
import org.eclipse.bpmn2.SubProcess;
import org.eclipse.bpmn2.Task;
import org.eclipse.bpmn2.UserTask;
import org.eclipse.emf.common.util.EList;
import org.eclipse.graphiti.features.IAddFeature;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.context.impl.AddConnectionContext;
import org.eclipse.graphiti.features.context.impl.AddContext;
import org.eclipse.graphiti.mm.pictograms.Anchor;
import org.eclipse.graphiti.mm.pictograms.ChopboxAnchor;
import org.eclipse.graphiti.mm.pictograms.ContainerShape;
import org.eclipse.graphiti.mm.pictograms.Diagram;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
import org.eclipse.graphiti.mm.pictograms.Shape;
import org.eclipse.graphiti.services.Graphiti;
import org.eclipse.graphiti.services.ILinkService;
/**
* @author Tijs Rademakers
*/
public class BpmnFileReader {
private static final int START_X = 30;
private static final int START_Y = 200;
private static final int EVENT_WIDTH = 35;
private static final int EVENT_HEIGHT = 35;
private static final int TASK_WIDTH = 105;
private static final int TASK_HEIGHT = 55;
private static final int GATEWAY_WIDTH = 40;
private static final int GATEWAY_HEIGHT = 40;
private static final int SEQUENCEFLOW_WIDTH = 40;
private Diagram diagram;
private IFeatureProvider featureProvider;
private String filename;
private InputStream fileStream;
private String processName;
private BpmnParser bpmnParser = new BpmnParser();
private Map<String, GraphicInfo> yMap = new HashMap<String, GraphicInfo>();
private List<SubProcess> subProcessList = new ArrayList<SubProcess>();
private boolean useBPMNDI = false;
public BpmnFileReader(String filename, Diagram diagram, IFeatureProvider featureProvider) {
this.filename = filename;
this.diagram = diagram;
this.featureProvider = featureProvider;
}
public BpmnFileReader(InputStream fileStream, String processName, Diagram diagram, IFeatureProvider featureProvider) {
this.fileStream = fileStream;
this.processName = processName;
this.diagram = diagram;
this.featureProvider = featureProvider;
}
public void openStream() {
File bpmnFile = new File(filename);
if(bpmnFile.exists() == false) {
System.out.println("bpmn file does not exist " + filename);
return;
}
processName = filename.substring(filename.lastIndexOf(File.separator) + 1);
processName = processName.substring(0, processName.indexOf("."));
try {
fileStream = new FileInputStream(bpmnFile);
} catch(Exception e) {
e.printStackTrace();
}
}
public void readBpmn() {
try {
XMLInputFactory xif = XMLInputFactory.newInstance();
InputStreamReader in = new InputStreamReader(fileStream, "UTF-8");
XMLStreamReader xtr = xif.createXMLStreamReader(in);
bpmnParser.parseBpmn(xtr);
if(bpmnParser.bpmnList.size() == 0) return;
org.eclipse.bpmn2.Process process = Bpmn2Factory.eINSTANCE.createProcess();
String processId = processName.replace(" ", "");
process.setId(processId);
if(bpmnParser.process != null && StringUtils.isNotEmpty(bpmnParser.process.getName())) {
process.setName(bpmnParser.process.getName());
} else {
process.setName(processName);
}
if(bpmnParser.process != null && StringUtils.isNotEmpty(bpmnParser.process.getNamespace())) {
process.setNamespace(bpmnParser.process.getNamespace());
}
Documentation documentation = null;
if(bpmnParser.process == null || bpmnParser.process.getDocumentation().size() == 0) {
documentation = Bpmn2Factory.eINSTANCE.createDocumentation();
documentation.setId("documentation_process");
documentation.setText("");
} else {
documentation = bpmnParser.process.getDocumentation().get(0);
}
process.getDocumentation().add(documentation);
if(bpmnParser.process != null && bpmnParser.process.getExecutionListeners().size() > 0) {
process.getExecutionListeners().addAll(bpmnParser.process.getExecutionListeners());
}
diagram.eResource().getContents().add(process);
if(PreferencesUtil.getBooleanPreference(Preferences.IMPORT_USE_BPMNDI) && bpmnParser.bpmdiInfoFound == true) {
useBPMNDI = true;
drawDiagramWithBPMNDI(diagram, featureProvider, bpmnParser.bpmnList, bpmnParser.sequenceFlowList,
bpmnParser.locationMap);
} else {
List<FlowElement> wrongOrderList = createDiagramElements(bpmnParser.bpmnList);
if(wrongOrderList.size() > 0) {
int counter = 0;
while(wrongOrderList.size() > 0 && counter < 10) {
int sizeBefore = wrongOrderList.size();
wrongOrderList = createDiagramElements(wrongOrderList);
if(sizeBefore <= wrongOrderList.size()) {
counter++;
} else {
counter = 0;
}
}
}
drawSequenceFlows();
}
setFriendlyIds();
xtr.close();
in.close();
fileStream.close();
} catch(Exception e) {
e.printStackTrace();
}
}
private List<FlowElement> createDiagramElements(List<FlowElement> flowList) {
SubProcess activeSubProcess = null;
List<FlowElement> wrongOrderList = new ArrayList<FlowElement>();
Set<BoundaryEvent> boundaryEventList = new HashSet<BoundaryEvent>();
// look for boundary events
for (FlowElement flowElement : flowList) {
if(flowElement instanceof BoundaryEvent) {
boundaryEventList.add((BoundaryEvent) flowElement);
}
}
// first look for start event
for (FlowElement startElement : flowList) {
if(startElement instanceof StartEvent) {
if(activeSubProcess == null || containsFlowElementId(activeSubProcess.getFlowElements(), startElement.getId()) == false) {
GraphicInfo graphicInfo = getNextGraphicInfo(null, startElement, yMap, boundaryEventList);
yMap.put(startElement.getId(), graphicInfo);
addBpmnElementToDiagram(startElement, graphicInfo, diagram);
processDiagramInSequence(startElement, flowList, activeSubProcess, wrongOrderList, boundaryEventList);
break;
}
}
}
return wrongOrderList;
}
private void processDiagramInSequence(FlowElement previousElement, List<FlowElement> flowList,
SubProcess activeSubProcess, List<FlowElement> wrongOrderList, Set<BoundaryEvent> boundaryEventList) {
for(SequenceFlowModel sequence : bpmnParser.sequenceFlowList) {
if(sequence.sourceRef != null && sequence.sourceRef.equals(previousElement.getId()) &&
sequence.targetRef != null && yMap.containsKey(sequence.targetRef) == false) {
for (FlowElement flowElement : flowList) {
if(sequence.targetRef.equals(flowElement.getId())) {
if(multipleIncomingSequenceFlows(flowElement, bpmnParser.sequenceFlowList) > 1) {
try {
getMaxX(flowElement.getId());
calculateDivergingElementY(flowElement, bpmnParser.sequenceFlowList);
} catch(FlowSourceNotFoundException e) {
if(activeSubProcess == null || containsFlowElementId(activeSubProcess.getFlowElements(), flowElement.getId()) == false) {
wrongOrderList.add(flowElement);
}
continue;
}
}
GraphicInfo graphicInfo = getNextGraphicInfo(previousElement, flowElement, yMap, boundaryEventList);
yMap.put(flowElement.getId(), graphicInfo);
if(flowElement instanceof SubProcess) {
activeSubProcess = (SubProcess) flowElement;
subProcessList.add(activeSubProcess);
} else if(activeSubProcess == null || containsFlowElementId(activeSubProcess.getFlowElements(),
flowElement.getId()) == false) {
addBpmnElementToDiagram(flowElement, graphicInfo, diagram);
}
processDiagramInSequence(flowElement, flowList, activeSubProcess, wrongOrderList, boundaryEventList);
if(boundaryEventList.size() > 0 &&
(flowElement instanceof SubProcess || flowElement instanceof CallActivity
|| flowElement instanceof Task)) {
if(flowElement instanceof SubProcess || activeSubProcess == null ||
containsFlowElementId(activeSubProcess.getFlowElements(), flowElement.getId()) == false) {
for (BoundaryEvent boundaryEvent : boundaryEventList) {
if(boundaryEvent.getAttachedToRef() != null && boundaryEvent.getAttachedToRef().getId().equals(flowElement.getId())) {
GraphicInfo boundaryGraphicInfo = getNextGraphicInfo(null, boundaryEvent, yMap, boundaryEventList);
yMap.put(boundaryEvent.getId(), boundaryGraphicInfo);
addBpmnElementToDiagram(boundaryEvent, boundaryGraphicInfo, diagram);
processDiagramInSequence(boundaryEvent, flowList, activeSubProcess, wrongOrderList, boundaryEventList);
}
}
}
}
break;
}
}
}
}
}
private boolean containsFlowElementId(List<FlowElement> flowElementList, String id) {
for (FlowElement flowElement : flowElementList) {
if(id.equals(flowElement.getId())) {
return true;
}
}
return false;
}
private GraphicInfo getNextGraphicInfo(FlowElement sourceFlowElement, FlowElement newFlowElement,
Map<String, GraphicInfo> yMap, Set<BoundaryEvent> boundaryEventList) {
GraphicInfo graphicInfo = new GraphicInfo();
GraphicInfo sourceInfo = null;
if(sourceFlowElement != null && yMap.containsKey(sourceFlowElement.getId())) {
sourceInfo = yMap.get(sourceFlowElement.getId());
if(sourceFlowElement instanceof BoundaryEvent && newFlowElement instanceof Task) {
sourceInfo.x -= 38;
}
}
int x = 0;
int y = 0;
if(sourceInfo != null) {
x = sourceInfo.x;
y = sourceInfo.y;
if(sourceFlowElement instanceof BoundaryEvent) {
y += SEQUENCEFLOW_WIDTH + TASK_HEIGHT;
} else {
if(multipleOutgoingSequenceFlows(sourceFlowElement, bpmnParser.sequenceFlowList) > 1) {
if(sourceFlowElement instanceof Gateway) {
x += GATEWAY_WIDTH;
} else if(sourceFlowElement instanceof Task) {
x += TASK_WIDTH;
} else if(sourceFlowElement instanceof Event) {
x += EVENT_WIDTH;
} else {
x += TASK_WIDTH;
}
y = calculateDirectElementChildY(sourceFlowElement, newFlowElement.getId(), sourceInfo.y, bpmnParser.sequenceFlowList);
} else if(sourceFlowElement instanceof Gateway) {
x += GATEWAY_WIDTH;
if(newFlowElement instanceof Task) {
y -= 7;
} else if(newFlowElement instanceof EndEvent) {
y += 3;
}
} else if(sourceFlowElement instanceof Event) {
x += EVENT_WIDTH;
if(newFlowElement instanceof Task) {
y -= 10;
}
} else if(sourceFlowElement instanceof SubProcess) {
x += sourceInfo.width;
int height = 0;
if(newFlowElement instanceof Task) {
height = TASK_HEIGHT;
} else if(newFlowElement instanceof Gateway) {
height = GATEWAY_HEIGHT;
} else if(newFlowElement instanceof Event) {
height = EVENT_HEIGHT;
}
y += ((sourceInfo.height / 2) - (height / 2));
} else {
x += TASK_WIDTH;
}
x += SEQUENCEFLOW_WIDTH;
if(newFlowElement instanceof EndEvent && sourceFlowElement instanceof Task) {
y += 10;
}
if(multipleIncomingSequenceFlows(newFlowElement, bpmnParser.sequenceFlowList) > 1) {
y = calculateDivergingElementY(newFlowElement, bpmnParser.sequenceFlowList);
x = getMaxX(newFlowElement.getId());
} else if(newFlowElement instanceof Gateway){
if(sourceFlowElement instanceof Task) {
y += 7;
} else if(sourceFlowElement instanceof StartEvent) {
y -= 2;
}
}
}
} else {
x = START_X;
y = START_Y;
}
graphicInfo.x = x;
graphicInfo.y = y;
if(newFlowElement instanceof Event) {
graphicInfo.height = EVENT_HEIGHT;
if(newFlowElement instanceof BoundaryEvent) {
BoundaryEvent boundaryEvent = (BoundaryEvent) newFlowElement;
if(boundaryEvent.getAttachedToRef() instanceof SubProcess && yMap.containsKey(boundaryEvent.getAttachedToRef().getId())) {
GraphicInfo attachGraphInfo = yMap.get(boundaryEvent.getAttachedToRef().getId());
graphicInfo.x = attachGraphInfo.x + attachGraphInfo.width / 2;
graphicInfo.y = attachGraphInfo.y + attachGraphInfo.height - 15;
} else if(yMap.containsKey(boundaryEvent.getAttachedToRef().getId())) {
GraphicInfo attachGraphInfo = yMap.get(boundaryEvent.getAttachedToRef().getId());
graphicInfo.x = attachGraphInfo.x + TASK_WIDTH - 25;
graphicInfo.y = attachGraphInfo.y + TASK_HEIGHT - 25;
}
}
} else if(newFlowElement instanceof Gateway) {
graphicInfo.height = GATEWAY_HEIGHT;
} else if(newFlowElement instanceof SubProcess) {
int width = 0;
int height = 0;
Map<String, GraphicInfo> subYMap = new HashMap<String, GraphicInfo>();
List<FlowElement> subFlowElementList = new ArrayList<FlowElement>();
// first go for start event
for(FlowElement startElement : ((SubProcess) newFlowElement).getFlowElements()) {
if(startElement instanceof StartEvent) {
GraphicInfo subGraphicInfo = new GraphicInfo();
subGraphicInfo.height = EVENT_HEIGHT;
subGraphicInfo.x = 20;
subGraphicInfo.y = 50;
subYMap.put(startElement.getId(), subGraphicInfo);
subFlowElementList.add(startElement);
if(subGraphicInfo.x > width)
width = subGraphicInfo.x;
if(subGraphicInfo.y > height)
height = subGraphicInfo.y;
processSubDiagramInSequence(startElement, (SubProcess) newFlowElement,
subFlowElementList, subYMap, boundaryEventList);
break;
}
}
for(String subElementId : subYMap.keySet()) {
GraphicInfo subGraphicInfo = subYMap.get(subElementId);
if(subGraphicInfo.x > width)
width = subGraphicInfo.x;
if(subGraphicInfo.y > height)
height = subGraphicInfo.y;
}
graphicInfo.width = width + 80;
graphicInfo.height = height + 40 + TASK_HEIGHT;
if(yMap.containsKey(sourceFlowElement.getId())) {
GraphicInfo subSourceInfo = yMap.get(sourceFlowElement.getId());
graphicInfo.y = subSourceInfo.y + (subSourceInfo.height / 2) - (graphicInfo.height / 2);
}
addBpmnElementToDiagram(newFlowElement, graphicInfo, diagram);
int differenceInitialStartEventAndSubProcessHeight = (graphicInfo.height / 2) - 50 - (EVENT_HEIGHT / 2);
ILinkService linkService = Graphiti.getLinkService();
List<PictogramElement> pictoList = linkService.getPictogramElements(diagram, (SubProcess) newFlowElement);
if(pictoList != null && pictoList.size() > 0) {
ContainerShape parent = (ContainerShape) pictoList.get(0);
for (FlowElement subFlowElement : subFlowElementList) {
GraphicInfo subInfoElem = subYMap.get(subFlowElement.getId());
subInfoElem.y += differenceInitialStartEventAndSubProcessHeight;
addBpmnElementToDiagram(subFlowElement, subYMap.get(subFlowElement.getId()), parent);
}
}
} else {
graphicInfo.height = TASK_HEIGHT;
}
graphicInfo.element = newFlowElement;
return graphicInfo;
}
private void processSubDiagramInSequence(FlowElement previousElement, SubProcess subProcess,
List<FlowElement> subFlowElementList, Map<String, GraphicInfo> subYMap, Set<BoundaryEvent> boundaryEventList) {
for(SequenceFlowModel sequence : bpmnParser.sequenceFlowList) {
if(sequence.sourceRef != null && sequence.sourceRef.equals(previousElement.getId()) &&
sequence.targetRef != null && subYMap.containsKey(sequence.targetRef) == false) {
for(FlowElement subFlowElement : subProcess.getFlowElements()) {
if(sequence.targetRef.equals(subFlowElement.getId())) {
FlowElement subSourceElement = sourceRef(subFlowElement.getId(), subYMap);
GraphicInfo subGraphicInfo = getNextGraphicInfo(subSourceElement, subFlowElement, subYMap, boundaryEventList);
if(subGraphicInfo.y < 0) {
subGraphicInfo.y = 0;
}
subYMap.put(subFlowElement.getId(), subGraphicInfo);
subFlowElementList.add(subFlowElement);
processSubDiagramInSequence(subFlowElement, subProcess, subFlowElementList, subYMap, boundaryEventList);
if(boundaryEventList.size() > 0 &&
(subFlowElement instanceof CallActivity || subFlowElement instanceof Task)) {
for (BoundaryEvent boundaryEvent : boundaryEventList) {
if(boundaryEvent.getAttachedToRef() != null && boundaryEvent.getAttachedToRef().getId().equals(subFlowElement.getId())) {
GraphicInfo boundaryGraphicInfo = getNextGraphicInfo(null, boundaryEvent, subYMap, boundaryEventList);
subYMap.put(boundaryEvent.getId(), boundaryGraphicInfo);
subFlowElementList.add(boundaryEvent);
processSubDiagramInSequence(boundaryEvent, subProcess, subFlowElementList, subYMap, boundaryEventList);
}
}
}
break;
}
}
}
}
}
private FlowElement sourceRef(String id, Map<String, GraphicInfo> graphInfoMap) {
FlowElement sourceRef = null;
String sourceRefString = null;
for (SequenceFlowModel sequenceFlowModel : bpmnParser.sequenceFlowList) {
if(sequenceFlowModel.targetRef.equals(id) && graphInfoMap.containsKey(sequenceFlowModel.sourceRef)) {
sourceRefString = sequenceFlowModel.sourceRef;
}
}
if(sourceRefString != null) {
for (FlowElement flowElement : bpmnParser.bpmnList) {
if(flowElement.getId().equals(sourceRefString)) {
sourceRef = flowElement;
}
}
}
return sourceRef;
}
private int getMaxX(String id) {
int maxX = 0;
String sourceRef = null;
for (SequenceFlowModel sequenceFlowModel : bpmnParser.sequenceFlowList) {
if(sequenceFlowModel.targetRef.equals(id)) {
if(yMap.containsKey(sequenceFlowModel.sourceRef)) {
int sourceX = yMap.get(sequenceFlowModel.sourceRef).x;
if(sourceX > maxX) {
maxX = sourceX;
sourceRef = sequenceFlowModel.sourceRef;
}
} else {
throw new FlowSourceNotFoundException();
}
}
}
if(sourceRef != null) {
for (FlowElement flowElement : bpmnParser.bpmnList) {
if(flowElement.getId().equals(sourceRef)) {
if(flowElement instanceof Event) {
maxX += EVENT_WIDTH;
} else if(flowElement instanceof Gateway) {
maxX += GATEWAY_WIDTH;
} else if(flowElement instanceof Task) {
maxX += TASK_WIDTH;
}
}
}
}
maxX += SEQUENCEFLOW_WIDTH;
return maxX;
}
private int multipleOutgoingSequenceFlows(FlowElement element, List<SequenceFlowModel> sequenceFlowList) {
int counter = 0;
for (SequenceFlowModel sequenceFlowModel : sequenceFlowList) {
if(sequenceFlowModel.sourceRef.equals(element.getId())) {
counter++;
}
}
return counter;
}
private int multipleIncomingSequenceFlows(FlowElement element, List<SequenceFlowModel> sequenceFlowList) {
int counter = 0;
for (SequenceFlowModel sequenceFlowModel : sequenceFlowList) {
if(sequenceFlowModel.targetRef.equals(element.getId())) {
String source = sequenceFlowModel.sourceRef;
int sourceCounter = 0;
for (SequenceFlowModel sourceFlowModel : sequenceFlowList) {
if(sourceFlowModel.sourceRef.equals(source)) {
for(FlowElement flowElement : bpmnParser.bpmnList) {
if(flowElement.getId().equals(source) && flowElement instanceof BoundaryEvent == false) {
sourceCounter++;
}
}
}
}
if(sourceCounter == 1) {
counter++;
}
}
}
return counter;
}
private int calculateDivergingElementY(FlowElement element, List<SequenceFlowModel> sequenceFlowList) {
if(element instanceof Gateway) {
GraphicInfo previousGateway = getDivergingGateway(element, sequenceFlowList, element.getClass().getName());
if(previousGateway != null) {
return previousGateway.y;
}
}
int y = 0;
List<SequenceFlowModel> flowList = new ArrayList<SequenceFlowModel>();
for (SequenceFlowModel sequenceFlowModel : sequenceFlowList) {
if(sequenceFlowModel.targetRef.equals(element.getId())) {
flowList.add(sequenceFlowModel);
}
}
if(flowList.size() % 2 == 0) {
int middleTop = (flowList.size() / 2) - 1;
int middleBottom = flowList.size() / 2;
if(yMap.containsKey(flowList.get(middleTop).sourceRef) && yMap.containsKey(flowList.get(middleBottom).sourceRef)) {
GraphicInfo middleTopInfo = yMap.get(flowList.get(middleTop).sourceRef);
GraphicInfo middleBottomInfo = yMap.get(flowList.get(middleBottom).sourceRef);
y = middleTopInfo.y + middleTopInfo.height;
int middleOfGap = (middleBottomInfo.y - (middleTopInfo.y + middleTopInfo.height)) / 2;
if(element instanceof Task) {
y += middleOfGap - (TASK_HEIGHT / 2);
} else if(element instanceof Gateway) {
y += middleOfGap - (GATEWAY_HEIGHT / 2);
} else if(element instanceof Event) {
y += middleOfGap - (EVENT_HEIGHT / 2);
} else {
y += middleOfGap - (TASK_HEIGHT / 2);
}
} else {
throw new FlowSourceNotFoundException();
}
} else {
int middle = ((flowList.size() - 1) / 2);
if(yMap.containsKey(flowList.get(middle).sourceRef)) {
GraphicInfo middleInfo = yMap.get(flowList.get(middle).sourceRef);
if(middleInfo.element instanceof Task) {
if(element instanceof Task) {
y = middleInfo.y;
} else if(element instanceof Gateway) {
y = middleInfo.y + 7;
} else if(element instanceof Event) {
y = middleInfo.y + 10;
} else {
y = middleInfo.y;
}
} else if(middleInfo.element instanceof Gateway) {
if(element instanceof Task) {
y = middleInfo.y - 7;
} else if(element instanceof Gateway) {
y = middleInfo.y;
} else if(element instanceof Event) {
y = middleInfo.y + 2;
} else {
y = middleInfo.y - 7;
}
} else if(middleInfo.element instanceof Event) {
if(element instanceof Task) {
y = middleInfo.y - 10;
} else if(element instanceof Gateway) {
y = middleInfo.y - 2;
} else if(element instanceof Event) {
y = middleInfo.y;
} else {
y = middleInfo.y - 10;
}
} else {
y = middleInfo.y;
}
} else {
throw new FlowSourceNotFoundException();
}
}
return y;
}
private GraphicInfo getDivergingGateway(FlowElement element, List<SequenceFlowModel> sequenceFlowList, String type) {
for (SequenceFlowModel sequenceFlowModel : sequenceFlowList) {
if(sequenceFlowModel.targetRef.equals(element.getId())) {
FlowElement sourceElement = sourceRef(sequenceFlowModel.targetRef, yMap);
if(sourceElement == null) {
throw new FlowSourceNotFoundException();
}
if(sourceElement.getClass().getName().equals(type)) {
return yMap.get(sourceElement.getId());
}
GraphicInfo sourceTreeInfo = getDivergingGateway(sourceElement, sequenceFlowList, type);
if(sourceTreeInfo != null) {
return sourceTreeInfo;
}
}
}
throw null;
}
private int calculateDirectElementChildY(FlowElement element, String id, int elementY, List<SequenceFlowModel> sequenceFlowList) {
int y = 0;
int counter = 0;
int index = 0;
for (SequenceFlowModel sequenceFlowModel : sequenceFlowList) {
if(sequenceFlowModel.sourceRef.equals(element.getId())) {
counter++;
}
if(sequenceFlowModel.targetRef.equals(id)) {
index = counter;
}
}
int childHeight = 20;
if(element instanceof Gateway) {
childHeight += GATEWAY_HEIGHT;
} else if(element instanceof Task) {
childHeight += TASK_HEIGHT;
} else if(element instanceof Event) {
childHeight += EVENT_HEIGHT;
} else {
childHeight += TASK_HEIGHT;
}
if(counter % 2 == 0) {
if(index > (counter / 2)) {
y = elementY + ((index - (counter / 2)) * childHeight);
} else {
y = elementY - (((counter / 2) - index + 1) * childHeight);
}
} else {
int middle = ((counter - 1) / 2) + 1;
if(index > middle) {
y = elementY + ((index - middle) * childHeight);
} else if(index == middle) {
y = elementY;
} else {
y = elementY - ((middle - index) * childHeight);
}
}
return y;
}
private void drawDiagramWithBPMNDI(Diagram diagram, IFeatureProvider featureProvider, List<FlowElement> bpmnList,
List<SequenceFlowModel> sequenceFlowList, Map<String, GraphicInfo> locationMap) {
for (FlowElement flowElement : bpmnList) {
String elementid = flowElement.getId();
GraphicInfo graphicInfo = locationMap.get(elementid);
addBpmnElementToDiagram(flowElement, graphicInfo, diagram);
}
drawSequenceFlows();
}
private void setFriendlyIds() {
Map<String, Integer> idMap = new HashMap<String, Integer>();
for (FlowElement flowElement : bpmnParser.bpmnList) {
if(StringUtils.isEmpty(flowElement.getId()) == false &&
flowElement.getId().matches("sid-\\w{4,12}-\\w{4,12}-\\w{4,12}-\\w{4,12}-\\w{4,12}") == false) {
continue;
}
if(flowElement instanceof StartEvent) {
flowElement.setId(getNextId("startevent", idMap));
} else if(flowElement instanceof EndEvent) {
if(((EndEvent) flowElement).getEventDefinitions().size() > 0) {
flowElement.setId(getNextId("errorendevent", idMap));
} else {
flowElement.setId(getNextId("endevent", idMap));
}
} else if(flowElement instanceof ExclusiveGateway) {
flowElement.setId(getNextId("exclusivegateway", idMap));
} else if(flowElement instanceof InclusiveGateway) {
flowElement.setId(getNextId("inclusivegateway", idMap));
} else if(flowElement instanceof ParallelGateway) {
flowElement.setId(getNextId("parallelgateway", idMap));
} else if(flowElement instanceof UserTask) {
flowElement.setId(getNextId("usertask", idMap));
} else if(flowElement instanceof ScriptTask) {
flowElement.setId(getNextId("scripttask", idMap));
} else if(flowElement instanceof ServiceTask) {
flowElement.setId(getNextId("servicetask", idMap));
} else if(flowElement instanceof ManualTask) {
flowElement.setId(getNextId("manualtask", idMap));
} else if(flowElement instanceof ReceiveTask) {
flowElement.setId(getNextId("receivetask", idMap));
} else if(flowElement instanceof BusinessRuleTask) {
flowElement.setId(getNextId("businessruletask", idMap));
} else if(flowElement instanceof MailTask) {
flowElement.setId(getNextId("mailtask", idMap));
} else if(flowElement instanceof BoundaryEvent) {
if(((BoundaryEvent) flowElement).getEventDefinitions().size() > 0) {
EventDefinition definition = ((BoundaryEvent) flowElement).getEventDefinitions().get(0);
if(definition instanceof ErrorEventDefinition) {
flowElement.setId(getNextId("boundaryerror", idMap));
} else {
flowElement.setId(getNextId("boundarytimer", idMap));
}
}
} else if(flowElement instanceof CallActivity) {
flowElement.setId(getNextId("callactivity", idMap));
} else if(flowElement instanceof SubProcess) {
flowElement.setId(getNextId("subprocess", idMap));
}
}
}
private String getNextId(String elementName, Map<String, Integer> idMap) {
if(idMap.containsKey(elementName)) {
idMap.put(elementName, idMap.get(elementName) + 1);
} else {
idMap.put(elementName, 1);
}
return elementName + idMap.get(elementName);
}
private void drawSequenceFlows() {
int sequenceCounter = 1;
for(SequenceFlowModel sequenceFlowModel : bpmnParser.sequenceFlowList) {
SequenceFlow sequenceFlow = Bpmn2Factory.eINSTANCE.createSequenceFlow();
if(StringUtils.isEmpty(sequenceFlowModel.id) || sequenceFlowModel.id.matches("sid-\\w{4,12}-\\w{4,12}-\\w{4,12}-\\w{4,12}-\\w{4,12}")) {
sequenceFlow.setId("flow" + sequenceCounter);
sequenceCounter++;
} else {
sequenceFlow.setId(sequenceFlowModel.id);
}
sequenceFlow.setSourceRef(getFlowNode(sequenceFlowModel.sourceRef));
sequenceFlow.setTargetRef(getFlowNode(sequenceFlowModel.targetRef));
if(sequenceFlow.getSourceRef() == null || sequenceFlow.getSourceRef().getId() == null ||
sequenceFlow.getTargetRef() == null || sequenceFlow.getTargetRef().getId() == null) continue;
if(sequenceFlowModel.conditionExpression != null) {
sequenceFlow.setConditionExpression(sequenceFlowModel.conditionExpression);
}
if(sequenceFlowModel.listenerList.size() > 0) {
sequenceFlow.getExecutionListeners().addAll(sequenceFlowModel.listenerList);
}
ContainerShape parent = null;
SubProcess subProcess = subProcessContains(sequenceFlow.getSourceRef(), subProcessList);
if(subProcess != null) {
ILinkService linkService = Graphiti.getLinkService();
List<PictogramElement> pictoList = linkService.getPictogramElements(diagram, subProcess);
if(pictoList != null && pictoList.size() > 0) {
parent = (ContainerShape) pictoList.get(0);
subProcess.getFlowElements().add(sequenceFlow);
}
}
if(parent == null) {
diagram.eResource().getContents().add(sequenceFlow);
parent = diagram;
}
sequenceFlow.getSourceRef().getOutgoing().add(sequenceFlow);
sequenceFlow.getTargetRef().getIncoming().add(sequenceFlow);
EList<Shape> shapeList = parent.getChildren();
ILinkService linkService = Graphiti.getLinkService();
Anchor sourceAnchor = null;
Anchor targetAnchor = null;
for (Shape shape : shapeList) {
FlowNode flowNode = (FlowNode) linkService.getBusinessObjectForLinkedPictogramElement(shape.getGraphicsAlgorithm().getPictogramElement());
if(flowNode == null || flowNode.getId() == null) continue;
if(sequenceFlow.getSourceRef() instanceof BoundaryEvent) {
if(flowNode instanceof Task || flowNode instanceof SubProcess) {
for(Shape subShape : ((ContainerShape) shape).getChildren()) {
FlowNode subFlowNode = (FlowNode) linkService.getBusinessObjectForLinkedPictogramElement(
subShape.getGraphicsAlgorithm().getPictogramElement());
if(subFlowNode == null || subFlowNode.getId() == null) continue;
if(subFlowNode.getId().equals(sequenceFlow.getSourceRef().getId())) {
EList<Anchor> anchorList = ((ContainerShape) subShape).getAnchors();
for (Anchor anchor : anchorList) {
if(anchor instanceof ChopboxAnchor) {
sourceAnchor = anchor;
break;
}
}
}
}
}
} else {
if(flowNode.getId().equals(sequenceFlow.getSourceRef().getId())) {
EList<Anchor> anchorList = ((ContainerShape) shape).getAnchors();
for (Anchor anchor : anchorList) {
if(anchor instanceof ChopboxAnchor) {
sourceAnchor = anchor;
break;
}
}
}
}
if(flowNode.getId().equals(sequenceFlow.getTargetRef().getId())) {
EList<Anchor> anchorList = ((ContainerShape) shape).getAnchors();
for (Anchor anchor : anchorList) {
if(anchor instanceof ChopboxAnchor) {
targetAnchor = anchor;
break;
}
}
}
}
AddConnectionContext addContext = new AddConnectionContext(sourceAnchor, targetAnchor);
if(useBPMNDI) {
List<GraphicInfo> bendpointList = new ArrayList<GraphicInfo>();
for (String sequenceGraphElement : bpmnParser.flowLocationMap.keySet()) {
if(sequenceFlowModel.id.equalsIgnoreCase(sequenceGraphElement)) {
List<GraphicInfo> pointList = bpmnParser.flowLocationMap.get(sequenceGraphElement);
if(pointList.size() > 2) {
for(int i = 1; i < pointList.size() - 1; i++) {
bendpointList.add(pointList.get(i));
}
}
}
}
addContext.putProperty("org.activiti.designer.bendpoints", bendpointList);
}
addContext.setNewObject(sequenceFlow);
featureProvider.addIfPossible(addContext);
if(bpmnParser.defaultFlowMap.containsValue(sequenceFlowModel.id)) {
Iterator<FlowNode> itDefaultFlow = bpmnParser.defaultFlowMap.keySet().iterator();
while(itDefaultFlow.hasNext()) {
FlowNode flowNode = itDefaultFlow.next();
String defaultId = bpmnParser.defaultFlowMap.get(flowNode);
if(defaultId.equalsIgnoreCase(sequenceFlowModel.id)) {
if(flowNode instanceof ExclusiveGateway) {
((ExclusiveGateway) flowNode).setDefault(sequenceFlow);
} else if(flowNode instanceof InclusiveGateway) {
((InclusiveGateway) flowNode).setDefault(sequenceFlow);
} else {
((Activity) flowNode).setDefault(sequenceFlow);
}
}
}
}
}
}
private SubProcess subProcessContains(FlowNode sourceRef, List<SubProcess> subProcessList) {
for (SubProcess subProcess : subProcessList) {
for (FlowElement flowElement : subProcess.getFlowElements()) {
if(flowElement.getId().equals(sourceRef.getId())) {
return subProcess;
}
}
}
return null;
}
private FlowNode getFlowNode(String elementid) {
FlowNode flowNode = null;
for(FlowElement flowElement : bpmnParser.bpmnList) {
if(flowElement.getId().equalsIgnoreCase(elementid)) {
flowNode = (FlowNode) flowElement;
}
}
return flowNode;
}
private void addBpmnElementToDiagram(FlowElement flowElement, GraphicInfo graphicInfo,
ContainerShape parent) {
if(flowElement instanceof BoundaryEvent) {
BoundaryEvent boundaryEvent = (BoundaryEvent) flowElement;
AddContext addContext = new AddContext();
boolean parentIsSubProcess = false;
if(boundaryEvent.getAttachedToRef() instanceof SubProcess) {
parentIsSubProcess = true;
}
ILinkService linkService = Graphiti.getLinkService();
List<PictogramElement> pictoList = linkService.getPictogramElements(diagram, boundaryEvent.getAttachedToRef());
if(pictoList != null && pictoList.size() > 0) {
addContext.setTargetContainer((ContainerShape) pictoList.get(0));
}
addContext.setNewObject(boundaryEvent);
if(parentIsSubProcess == true) {
addContext.setX(addContext.getTargetContainer().getGraphicsAlgorithm().getWidth() / 2);
addContext.setY(addContext.getTargetContainer().getGraphicsAlgorithm().getHeight() - 15);
} else {
addContext.setX(TASK_WIDTH - 25);
addContext.setY(TASK_HEIGHT - 25);
}
IAddFeature addFeature = featureProvider.getAddFeature(addContext);
if (addFeature.canAdd(addContext)) {
addFeature.add(addContext);
}
return;
}
if(flowElement instanceof UserTask) {
UserTask userTask = (UserTask) flowElement;
if(userTask.getCandidateUsers() != null && userTask.getCandidateUsers().size() > 0) {
for (CandidateUser candidateUser : userTask.getCandidateUsers()) {
diagram.eResource().getContents().add(candidateUser);
}
}
if(userTask.getCandidateGroups() != null && userTask.getCandidateGroups().size() > 0) {
for (CandidateGroup candidateGroup : userTask.getCandidateGroups()) {
diagram.eResource().getContents().add(candidateGroup);
}
}
} else if(flowElement instanceof ServiceTask) {
ServiceTask serviceTask = (ServiceTask) flowElement;
if(serviceTask.getFieldExtensions() != null && serviceTask.getFieldExtensions().size() > 0) {
for (FieldExtension fieldExtension : serviceTask.getFieldExtensions()) {
diagram.eResource().getContents().add(fieldExtension);
}
}
}
AddContext addContext = new AddContext();
addContext.setNewObject(flowElement);
addContext.setTargetContainer(parent);
addContext.setX(graphicInfo.x);
if(useBPMNDI) {
addContext.setHeight(graphicInfo.height);
addContext.setWidth(graphicInfo.width);
}
if(flowElement instanceof StartEvent || flowElement instanceof EndEvent) {
if(useBPMNDI == false && graphicInfo.height < EVENT_HEIGHT) {
addContext.setY(graphicInfo.y - 25);
} else {
addContext.setY(graphicInfo.y);
}
} else if(flowElement instanceof ExclusiveGateway || flowElement instanceof InclusiveGateway ||
flowElement instanceof ParallelGateway) {
if(useBPMNDI == false && graphicInfo.height < GATEWAY_HEIGHT) {
addContext.setY(graphicInfo.y - 20);
} else {
addContext.setY(graphicInfo.y);
}
} else if(flowElement instanceof SubProcess) {
addContext.setHeight(graphicInfo.height);
addContext.setWidth(graphicInfo.width);
addContext.setY(graphicInfo.y);
} else {
addContext.setY(graphicInfo.y);
}
IAddFeature addFeature = featureProvider.getAddFeature(addContext);
if (addFeature.canAdd(addContext)) {
addFeature.add(addContext);
}
}
}