/* 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.export.bpmn20.export; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.stream.XMLStreamWriter; import org.eclipse.bpmn2.BoundaryEvent; import org.eclipse.bpmn2.FlowElement; import org.eclipse.bpmn2.FlowNode; import org.eclipse.bpmn2.Process; import org.eclipse.bpmn2.SequenceFlow; import org.eclipse.bpmn2.SubProcess; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm; import org.eclipse.graphiti.mm.algorithms.styles.Point; import org.eclipse.graphiti.mm.pictograms.Connection; import org.eclipse.graphiti.mm.pictograms.ContainerShape; import org.eclipse.graphiti.mm.pictograms.Diagram; import org.eclipse.graphiti.mm.pictograms.FreeFormConnection; 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 BpmnDIExport implements ActivitiNamespaceConstants { private static Map<String, GraphicsAlgorithm> diFlowNodeMap = new HashMap<String, GraphicsAlgorithm>(); private static Diagram diagram; private static XMLStreamWriter xtw; public static void createDIXML(Process process, Diagram inputDiagram, XMLStreamWriter inputXtw) throws Exception { diagram = inputDiagram; xtw = inputXtw; ILinkService linkService = Graphiti.getLinkService(); EList<EObject> contents = diagram.eResource().getContents(); xtw.writeStartElement(BPMNDI_PREFIX, "BPMNDiagram", BPMNDI_NAMESPACE); xtw.writeAttribute("id", "BPMNDiagram_" + process.getId()); xtw.writeStartElement(BPMNDI_PREFIX, "BPMNPlane", BPMNDI_NAMESPACE); xtw.writeAttribute("bpmnElement", process.getId()); xtw.writeAttribute("id", "BPMNPlane_" + process.getId()); diFlowNodeMap = new HashMap<String, GraphicsAlgorithm>(); for (EObject bpmnObject : contents) { if (bpmnObject instanceof FlowNode) { FlowNode node = (FlowNode) bpmnObject; if(node.getIncoming().size() == 0 && node.getOutgoing().size() == 0) { continue; } writeBpmnElement(node, diagram, null); if(bpmnObject instanceof SubProcess) { for (FlowElement subFlowElement : ((SubProcess) node).getFlowElements()) { if (subFlowElement instanceof FlowNode) { List<PictogramElement> pictoList = linkService.getPictogramElements(diagram, node); if(pictoList != null && pictoList.size() > 0) { ContainerShape parent = (ContainerShape) pictoList.get(0); writeBpmnElement((FlowNode) subFlowElement, parent, (SubProcess) node); } } } for (FlowElement subFlowElement : ((SubProcess) node).getFlowElements()) { if (subFlowElement instanceof SequenceFlow) { List<PictogramElement> pictoList = linkService.getPictogramElements(diagram, node); if(pictoList != null && pictoList.size() > 0) { ContainerShape parent = (ContainerShape) pictoList.get(0); writeBpmnEdge((SequenceFlow) subFlowElement, parent, (SubProcess) node); } } } } } } for (EObject bpmnObject : contents) { if (bpmnObject instanceof SequenceFlow) { writeBpmnEdge((SequenceFlow) bpmnObject, diagram, null); } } xtw.writeEndElement(); xtw.writeEndElement(); } private static void writeBpmnElement(FlowNode flowNode, ContainerShape parent, SubProcess subProcess) throws Exception { ILinkService linkService = Graphiti.getLinkService(); if(flowNode instanceof BoundaryEvent) { if(((BoundaryEvent) flowNode).getAttachedToRef() == null || ((BoundaryEvent) flowNode).getAttachedToRef().getId() == null) { return; } } for (Shape shape : parent.getChildren()) { EObject shapeBO = linkService.getBusinessObjectForLinkedPictogramElement(shape.getGraphicsAlgorithm().getPictogramElement()); if(flowNode instanceof BoundaryEvent && shapeBO instanceof BoundaryEvent && ((BoundaryEvent) shapeBO).getId().equals(flowNode.getId())) { BoundaryEvent shapeBoundaryEvent = (BoundaryEvent) shapeBO; diFlowNodeMap.put(flowNode.getId(), shape.getGraphicsAlgorithm()); java.awt.Point attachedPoint = findAttachedShape(shapeBoundaryEvent.getAttachedToRef().getId(), parent.getChildren()); if(attachedPoint != null) { xtw.writeStartElement(BPMNDI_PREFIX, "BPMNShape", BPMNDI_NAMESPACE); xtw.writeAttribute("bpmnElement", flowNode.getId()); xtw.writeAttribute("id", "BPMNShape_" + flowNode.getId()); xtw.writeStartElement(OMGDC_PREFIX, "Bounds", OMGDC_NAMESPACE); xtw.writeAttribute("height", "" + shape.getGraphicsAlgorithm().getHeight()); xtw.writeAttribute("width", "" + shape.getGraphicsAlgorithm().getWidth()); if(subProcess != null) { xtw.writeAttribute("x", "" + (shape.getGraphicsAlgorithm().getX() + attachedPoint.getX())); xtw.writeAttribute("y", "" + (shape.getGraphicsAlgorithm().getY() + attachedPoint.getY())); } else { xtw.writeAttribute("x", "" + shape.getGraphicsAlgorithm().getX()); xtw.writeAttribute("y", "" + shape.getGraphicsAlgorithm().getY()); } xtw.writeEndElement(); xtw.writeEndElement(); } } else { if (shapeBO instanceof FlowNode) { FlowNode shapeFlowNode = (FlowNode) shapeBO; if (shapeFlowNode.getId().equals(flowNode.getId())) { xtw.writeStartElement(BPMNDI_PREFIX, "BPMNShape", BPMNDI_NAMESPACE); xtw.writeAttribute("bpmnElement", flowNode.getId()); xtw.writeAttribute("id", "BPMNShape_" + flowNode.getId()); diFlowNodeMap.put(flowNode.getId(), shape.getGraphicsAlgorithm()); xtw.writeStartElement(OMGDC_PREFIX, "Bounds", OMGDC_NAMESPACE); xtw.writeAttribute("height", "" + shape.getGraphicsAlgorithm().getHeight()); xtw.writeAttribute("width", "" + shape.getGraphicsAlgorithm().getWidth()); if(subProcess != null) { xtw.writeAttribute("x", "" + (shape.getGraphicsAlgorithm().getX() + shape.getContainer().getGraphicsAlgorithm().getX())); xtw.writeAttribute("y", "" + (shape.getGraphicsAlgorithm().getY() + shape.getContainer().getGraphicsAlgorithm().getY())); } else { xtw.writeAttribute("x", "" + shape.getGraphicsAlgorithm().getX()); xtw.writeAttribute("y", "" + shape.getGraphicsAlgorithm().getY()); } xtw.writeEndElement(); xtw.writeEndElement(); } } } } } private static java.awt.Point findAttachedShape(String shapeid, EList<Shape> shapeList) { ILinkService linkService = Graphiti.getLinkService(); for (Shape shape : shapeList) { EObject shapeBO = linkService.getBusinessObjectForLinkedPictogramElement(shape.getGraphicsAlgorithm().getPictogramElement()); if(shapeBO instanceof FlowNode) { FlowNode shapeFlowNode = (FlowNode) shapeBO; if (shapeFlowNode.getId().equals(shapeid)) { ContainerShape parentContainerShape = ((ContainerShape) shape).getContainer(); if(parentContainerShape instanceof Diagram == false) { EObject parentShapeBO = linkService.getBusinessObjectForLinkedPictogramElement( parentContainerShape.getGraphicsAlgorithm().getPictogramElement()); if(parentShapeBO instanceof SubProcess) { return new java.awt.Point(parentContainerShape.getGraphicsAlgorithm().getX(), parentContainerShape.getGraphicsAlgorithm().getY()); } else { return new java.awt.Point(shape.getGraphicsAlgorithm().getX(), shape.getGraphicsAlgorithm().getY()); } } else { return new java.awt.Point(shape.getGraphicsAlgorithm().getX(), shape.getGraphicsAlgorithm().getY()); } } } } return null; } private static void writeBpmnEdge(SequenceFlow sequenceFlow, ContainerShape parent, SubProcess subProcess) throws Exception { if (diFlowNodeMap.containsKey(sequenceFlow.getSourceRef().getId()) && diFlowNodeMap.containsKey(sequenceFlow.getTargetRef().getId())) { ILinkService linkService = Graphiti.getLinkService(); FreeFormConnection freeFormConnection = null; EList<Point> bendPointList = null; for(Connection connection : diagram.getConnections()) { EObject linkedSequenceFlowObj = linkService.getBusinessObjectForLinkedPictogramElement( connection.getGraphicsAlgorithm().getPictogramElement()); if(linkedSequenceFlowObj instanceof SequenceFlow == false) continue; SequenceFlow linkedSequenceFlow = (SequenceFlow) linkedSequenceFlowObj; if(linkedSequenceFlow.getId().equals(sequenceFlow.getId()) == false) continue; freeFormConnection = (FreeFormConnection) connection; bendPointList = freeFormConnection.getBendpoints(); } if(freeFormConnection == null) return; xtw.writeStartElement(BPMNDI_PREFIX, "BPMNEdge", BPMNDI_NAMESPACE); xtw.writeAttribute("bpmnElement", sequenceFlow.getId()); xtw.writeAttribute("id", "BPMNEdge_" + sequenceFlow.getId()); GraphicsAlgorithm sourceConnection = diFlowNodeMap.get(sequenceFlow.getSourceRef().getId()); GraphicsAlgorithm targetConnection = diFlowNodeMap.get(sequenceFlow.getTargetRef().getId()); int subProcessX = 0; int subProcessY = 0; if(subProcess != null) { GraphicsAlgorithm subProcessGraphics = diFlowNodeMap.get(subProcess.getId()); if(subProcessGraphics != null) { subProcessX = subProcessGraphics.getX(); subProcessY = subProcessGraphics.getY(); } } int sourceX = subProcessX + sourceConnection.getX(); int sourceY = subProcessY + sourceConnection.getY(); int sourceWidth = sourceConnection.getWidth(); int sourceHeight = sourceConnection.getHeight(); int sourceMiddleX = sourceX + (sourceWidth / 2); int sourceMiddleY = sourceY + (sourceHeight / 2); int sourceBottomY = sourceY + sourceHeight; int targetX = subProcessX + targetConnection.getX(); int targetY = subProcessY + targetConnection.getY(); int targetWidth = targetConnection.getWidth(); int targetHeight = targetConnection.getHeight(); int targetMiddleX = targetX + (targetWidth / 2); int targetMiddleY = targetY + (targetHeight / 2); int targetBottomY = targetY + targetHeight; java.awt.Point lastWayPoint = null; if (sequenceFlow.getSourceRef() instanceof BoundaryEvent) { lastWayPoint = createWayPoint(sourceConnection.getX() + (sourceConnection.getWidth() / 2) + subProcessX, sourceConnection.getY() + sourceConnection.getHeight() + subProcessY, xtw); } else { if((bendPointList == null || bendPointList.size() == 0)) { if((sourceBottomY + 11) < targetY) { lastWayPoint = createWayPoint(sourceMiddleX, sourceY + sourceHeight, xtw); } else if((sourceY - 11) > (targetY + targetHeight)) { lastWayPoint = createWayPoint(sourceMiddleX, sourceY, xtw); } else if(sourceX > targetX) { lastWayPoint = createWayPoint(sourceX, sourceMiddleY, xtw); } else { lastWayPoint = createWayPoint(sourceX + sourceWidth, sourceMiddleY, xtw); } } else { Point bendPoint = bendPointList.get(0); if((sourceBottomY + 5) < bendPoint.getY()) { lastWayPoint = createWayPoint(sourceMiddleX, sourceY + sourceHeight, xtw); } else if((sourceY - 5) > bendPoint.getY()) { lastWayPoint = createWayPoint(sourceMiddleX, sourceY, xtw); } else if(sourceX > bendPoint.getX()) { lastWayPoint = createWayPoint(sourceX, sourceMiddleY, xtw); } else { lastWayPoint = createWayPoint(sourceX + sourceWidth, sourceMiddleY, xtw); } } } if(bendPointList != null && bendPointList.size() > 0) { for (Point point : bendPointList) { lastWayPoint = createWayPoint(point.getX(), point.getY(), xtw); } } int difference = 5; if((bendPointList == null || bendPointList.size() == 0)) { difference = 11; } if((targetBottomY + difference) < lastWayPoint.getY()) { lastWayPoint = createWayPoint(targetMiddleX, targetY + targetHeight, xtw); } else if((targetY - difference) > lastWayPoint.getY()) { lastWayPoint = createWayPoint(targetMiddleX, targetY, xtw); } else if(targetX > lastWayPoint.getX()) { lastWayPoint = createWayPoint(targetX, targetMiddleY, xtw); } else { lastWayPoint = createWayPoint(targetX + targetWidth, targetMiddleY, xtw); } xtw.writeEndElement(); } } private static java.awt.Point createWayPoint(int x, int y, XMLStreamWriter xtw) throws Exception { xtw.writeStartElement(OMGDI_PREFIX, "waypoint", OMGDI_NAMESPACE); xtw.writeAttribute("x", "" + x); xtw.writeAttribute("y", "" + y); xtw.writeEndElement(); return new java.awt.Point(x, y); } }