From 901f047405a033b3b8f039cfa442c2d74140c1ea Mon Sep 17 00:00:00 2001 From: qinoy Date: Mon, 26 Dec 2022 18:53:41 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=8A=E5=88=A9=E9=A1=B9=E7=9B=AE=20?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E8=BD=AC=E6=8D=A2=E5=8A=9F=E8=83=BD=20?= =?UTF-8?q?=E5=9B=BE=E5=BD=A2=E9=97=B4=E8=B7=9D=E9=97=AE=E9=A2=98=E4=BB=A5?= =?UTF-8?q?=E5=8F=8A=E8=BF=9E=E7=BA=BF=E9=94=9A=E7=82=B9=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E8=A7=A3=E5=86=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...m.actionsoft.apps.coe.pal.modelconvert.jar | Bin 94074 -> 97338 bytes .../modelconvert/constant/ShapeConstant.java | 6 + .../modelconvert/strategy/impl/EpcToBPMN.java | 1250 +++++++++-------- .../pal/modelconvert/util/ConvertUtil.java | 140 +- 4 files changed, 773 insertions(+), 623 deletions(-) diff --git a/com.actionsoft.apps.coe.pal.modelconvert/lib/com.actionsoft.apps.coe.pal.modelconvert.jar b/com.actionsoft.apps.coe.pal.modelconvert/lib/com.actionsoft.apps.coe.pal.modelconvert.jar index c81af08eace9a42ed8287d5988a5f27428652454..dbe3c075af36c9e9f116c9aa11bffc5e9cc2ca26 100644 GIT binary patch delta 32344 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

QvOl7m0$>C(XK-l2ohX;d< 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 delta 29178 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 { - JSONObject epcElement = elements.getJSONObject(key); - String shapeName = epcElement.getString("name"); - JSONObject props = epcElement.getJSONObject("props"); - // 处理图形 - if (!"linker".equals(shapeName)){ - // 记录当前EPC图形的中心点坐标 - double shapeCenterPoiX = props.getDoubleValue("x") + (props.getDoubleValue("w") / 2); - double shapeCenterPoiY = props.getDoubleValue("y") + (props.getDoubleValue("h") / 2); - Position epcShapePoi = new Position(shapeCenterPoiX, shapeCenterPoiY); - // 构建BPMN图形的中心点坐标 相当于向右旋转90度的效果 - Position bpmnShapeCenterPoi = new Position(shapeCenterPoiY, epcPageWidth - shapeCenterPoiX); - // 根据映射关系构建转换后的BPMN图形 - JSONObject shapeDefinition = CoeDesignerUtil.getShapeDefinition(targetMethod, ConvertUtil.epcToBPMNShapeMapping(shapeName)); - // 如果为空shapeDefinition可能是需求要求的图形映射关系不包含当前图形 - if (shapeDefinition != null){ - // 计算转后BPMN图形的起始坐标 - JSONObject propsObj = shapeDefinition.getJSONObject("props"); - double w = propsObj.getDoubleValue("w"); - double h = propsObj.getDoubleValue("h"); - double x = bpmnShapeCenterPoi.getX() - w / 2; - double y = bpmnShapeCenterPoi.getY() - h / 2; - propsObj.put("x",x); - propsObj.put("y",y); - int zindex = zIndexMap.get("zindex").intValue(); - zIndexMap.put("zindex",zindex++); - propsObj.put("zindex",zindex++); - propsObj.put("angle",props.getIntValue("angle")); - shapeDefinition.put("props",propsObj); - shapeDefinition.put("text",epcElement.getString("text")); - // 补充图形初始化结构的默认属性 - this.handleDefaultProperty(shapeDefinition); - // 记录下图形ID的映射关系 - String newShapeId = UUIDGener.getObjectId(); - shapeDefinition.put("id",newShapeId); + this.handleShapeConvert(elements,bpmnElements,zIndexMap,epcPageWidth,targetMethod); + // 1.2 根据原本的连线关系处理转换后的图形间距 返回画布最新宽度 + double maxX = this.handleShapeSpace(elements,bpmnElements); - ConvertShapeIdMapping.getInstance().load(ConvertType.EPC_BPMN,key,newShapeId); - - bpmnElements.put(newShapeId,shapeDefinition); - } - } - }); - - // 1.2 第二次循环 根据连线关系生成新的连线 - elements.keySet().stream() - .filter(key -> "linker".equals(elements.getJSONObject(key).getString("name"))) - .filter(key -> { - // 过滤掉既没有图形链接的线 - boolean flag = false; - JSONObject epcLinkerObj = elements.getJSONObject(key); - JSONObject epcLinkerFromObj = epcLinkerObj.getJSONObject("from"); - JSONObject epcLinkerToObj = epcLinkerObj.getJSONObject("to"); - String epcLinkerFromId = epcLinkerFromObj.getString("id"); - String epcLinkerToId = epcLinkerToObj.getString("id"); - if (UtilString.isNotEmpty(epcLinkerFromId) && UtilString.isNotEmpty(epcLinkerToId)){ - flag = true; - } - return flag; - }) - .forEach(key -> { - JSONObject epcLinkerObj = elements.getJSONObject(key); - JSONObject epcLinkerFromObj = epcLinkerObj.getJSONObject("from"); - JSONObject epcLinkerToObj = epcLinkerObj.getJSONObject("to"); - String epcLinkerFromId = epcLinkerFromObj.getString("id"); - Position epcLinkerFromPoi = new Position(epcLinkerFromObj.getDoubleValue("x"),epcLinkerFromObj.getDoubleValue("y")); - String epcLinkerToId = epcLinkerToObj.getString("id"); - Position epcLinkerToPoi = new Position(epcLinkerToObj.getDoubleValue("x"),epcLinkerToObj.getDoubleValue("y")); - JSONObject epcLinkerProps = epcLinkerObj.getJSONObject("props"); - JSONArray epcLinkerPoints = epcLinkerObj.getJSONArray("points"); - // System.out.println("=======>>> " + epcLinkerObj.getString("text")); - Position epcLinkerPoint1 = new Position(((JSONObject)epcLinkerPoints.get(0)).getDoubleValue("x"),((JSONObject)epcLinkerPoints.get(0)).getDoubleValue("y")); - Position epcLinkerPoint2 = null; - if (epcLinkerPoints.size() > 1){ - epcLinkerPoint2 = new Position(((JSONObject)epcLinkerPoints.get(1)).getDoubleValue("x"),((JSONObject)epcLinkerPoints.get(1)).getDoubleValue("y")); - } - - JSONObject bpmnLinkerObj = JSONObject.parseObject(LinkerDefConstant.linker); - String bpmnLinkerDefId = UUIDGener.getObjectId(); - String bpmnShapeFromId = ConvertShapeIdMapping.getInstance().getTargetShapeId(ConvertType.EPC_BPMN,epcLinkerFromId); - String bpmnShapeToId = ConvertShapeIdMapping.getInstance().getTargetShapeId(ConvertType.EPC_BPMN,epcLinkerToId); - bpmnLinkerObj.put("id",bpmnLinkerDefId); - bpmnLinkerObj.put("text",epcLinkerObj.getString("text")); - - JSONObject bpmnLinkerFromObj = new JSONObject(); - bpmnLinkerFromObj.put("id",bpmnShapeFromId); - JSONObject bpmnLinkerToObj = new JSONObject(); - bpmnLinkerToObj.put("id",bpmnShapeToId); - - JSONObject bpmnShapeFromObj = bpmnElements.getJSONObject(bpmnShapeFromId); - JSONObject bpmnShapeToObj = bpmnElements.getJSONObject(bpmnShapeToId); - - JSONObject bpmnShapeFromProps = bpmnShapeFromObj.getJSONObject("props"); - JSONObject bpmnShapeToProps = bpmnShapeToObj.getJSONObject("props"); - - JSONArray points = new JSONArray(); - if (epcLinkerFromPoi.getX() == epcLinkerToPoi.getX() - && epcLinkerFromPoi.getY() != epcLinkerToPoi.getY() - && epcLinkerPoints.size() == 2 - && epcLinkerPoint1.equals(epcLinkerPoint2)){ // 说明是连线原本是垂直方向的 转换后连线方向应为水平方向 - if (epcLinkerFromPoi.getY() < epcLinkerToPoi.getY()){ // 连线是自上而下的走向 转换后连线方向应为 自左向右 - // 处理from坐标 - bpmnLinkerFromObj.put("x",bpmnShapeFromProps.getDoubleValue("x") + bpmnShapeFromProps.getDoubleValue("w")); - bpmnLinkerFromObj.put("y",bpmnShapeFromProps.getDoubleValue("y") + (bpmnShapeFromProps.getDoubleValue("h") / 2)); - bpmnLinkerFromObj.put("angle",LinkerDefConstant.ANGLE_LEFT); - // 处理to坐标 - bpmnLinkerToObj.put("x",bpmnShapeToProps.getDoubleValue("x")); - bpmnLinkerToObj.put("y",bpmnShapeToProps.getDoubleValue("y") + (bpmnShapeToProps.getDoubleValue("h") / 2)); - bpmnLinkerToObj.put("angle",LinkerDefConstant.ANGLE_RIGHT); - // 直线的话会有两个相同坐标点的折点 坐标点为两个图形的距离的一半 - JSONObject point1 = new JSONObject(); - point1.put("x",bpmnLinkerFromObj.getDoubleValue("x") + ((bpmnLinkerToObj.getDoubleValue("x") - bpmnLinkerFromObj.getDoubleValue("x")) / 2)); - point1.put("y",bpmnLinkerToObj.getDoubleValue("y")); - points.add(point1); - JSONObject point2 = new JSONObject(); - point2.put("x",bpmnLinkerFromObj.getDoubleValue("x") + ((bpmnLinkerToObj.getDoubleValue("x") - bpmnLinkerFromObj.getDoubleValue("x")) / 2)); - point2.put("y",bpmnLinkerToObj.getDoubleValue("y")); - points.add(point2); - }else { // 连线是自下而上的走向 转换后连线方向应为 自右向左 - bpmnLinkerFromObj.put("x",bpmnShapeFromProps.getDoubleValue("x")); - bpmnLinkerFromObj.put("y",bpmnShapeFromProps.getDoubleValue("y") + (bpmnShapeFromProps.getDoubleValue("h") / 2)); - bpmnLinkerFromObj.put("angle",LinkerDefConstant.ANGLE_RIGHT); - bpmnLinkerToObj.put("x",bpmnShapeToProps.getDoubleValue("x") + bpmnShapeToProps.getDoubleValue("x")); - bpmnLinkerToObj.put("y",bpmnShapeToProps.getDoubleValue("y") + bpmnShapeToProps.getDoubleValue("h") / 2); - bpmnLinkerToObj.put("angle",LinkerDefConstant.ANGLE_LEFT); - JSONObject point3 = new JSONObject(); - point3.put("x",bpmnLinkerToObj.getDoubleValue("x") + ((bpmnLinkerFromObj.getDoubleValue("x") - bpmnLinkerToObj.getDoubleValue("x")) / 2)); - point3.put("y",bpmnLinkerToObj.getDoubleValue("y")); - points.add(point3); - JSONObject point4 = new JSONObject(); - point4.put("x",bpmnLinkerToObj.getDoubleValue("x") + ((bpmnLinkerFromObj.getDoubleValue("x") - bpmnLinkerToObj.getDoubleValue("x")) / 2)); - point4.put("y",bpmnLinkerToObj.getDoubleValue("y")); - points.add(point4); - } - }else if (epcLinkerFromPoi.getY() == epcLinkerToPoi.getY() - && epcLinkerFromPoi.getX() != epcLinkerToPoi.getX() - && epcLinkerPoints.size() == 2 - && epcLinkerPoint1.equals(epcLinkerPoint2)){ // 说明连线原本是水平方向的 转换后连线方向应为垂直方向 - if (epcLinkerFromPoi.getX() < epcLinkerToPoi.getX()){ // 连线是自左而右的走向 转换后连线方向应为 自下而上 - // 处理from坐标 - bpmnLinkerFromObj.put("x",bpmnShapeFromProps.getDoubleValue("x") + (bpmnShapeFromProps.getDoubleValue("w") / 2)); - bpmnLinkerFromObj.put("y",bpmnShapeFromProps.getDoubleValue("y")); - bpmnLinkerFromObj.put("angle",LinkerDefConstant.ANGLE_DOWN); - // 处理to坐标 - bpmnLinkerToObj.put("x",bpmnShapeToProps.getDoubleValue("x") + (bpmnShapeToProps.getDoubleValue("w") / 2)); - bpmnLinkerToObj.put("y",bpmnShapeToProps.getDoubleValue("y") + bpmnShapeToProps.getDoubleValue("h")); - bpmnLinkerToObj.put("angle",LinkerDefConstant.ANGLE_UP); - // 直线的话会有两个相同坐标点的折点 坐标点为两个图形的距离的一半 - JSONObject point5 = new JSONObject(); - point5.put("x",bpmnLinkerFromObj.getDoubleValue("x")); - point5.put("y",bpmnLinkerToObj.getDoubleValue("y") + ((bpmnLinkerFromObj.getDoubleValue("y") - bpmnLinkerToObj.getDoubleValue("y")) / 2)); - points.add(point5); - JSONObject point6 = new JSONObject(); - point6.put("x",bpmnLinkerFromObj.getDoubleValue("x")); - point6.put("y",bpmnLinkerToObj.getDoubleValue("y") + ((bpmnLinkerFromObj.getDoubleValue("y") - bpmnLinkerToObj.getDoubleValue("y")) / 2)); - points.add(point6); - }else { // 连线是自右向左的走向 转换后连线方向应为自上而下 - bpmnLinkerFromObj.put("x",bpmnShapeFromProps.getDoubleValue("x") + (bpmnShapeFromProps.getDoubleValue("w") / 2)); - bpmnLinkerFromObj.put("y",bpmnShapeFromProps.getDoubleValue("y") + bpmnShapeFromProps.getDoubleValue("h")); - bpmnLinkerFromObj.put("angle",LinkerDefConstant.ANGLE_UP); - bpmnLinkerToObj.put("x",bpmnShapeToProps.getDoubleValue("x") + (bpmnShapeToProps.getDoubleValue("w") / 2)); - bpmnLinkerToObj.put("y",bpmnShapeToProps.getDoubleValue("y")); - bpmnLinkerToObj.put("angle",LinkerDefConstant.ANGLE_DOWN); - JSONObject point7 = new JSONObject(); - point7.put("x",bpmnLinkerFromObj.getDoubleValue("x")); - point7.put("y",bpmnLinkerFromObj.getDoubleValue("y") + (bpmnLinkerToObj.getDoubleValue("y") - bpmnLinkerFromObj.getDoubleValue("y")) / 2); - points.add(point7); - JSONObject point8 = new JSONObject(); - point8.put("x",bpmnLinkerFromObj.getDoubleValue("x")); - point8.put("y",bpmnLinkerFromObj.getDoubleValue("y") + (bpmnLinkerToObj.getDoubleValue("y") - bpmnLinkerFromObj.getDoubleValue("y")) / 2); - points.add(point8); - } - }else { // 处理带明显折点的连线 - // 判断转换后的连线是在图形的上方还是下方 - if (epcLinkerFromObj.getDoubleValue("x") < epcLinkerPoint1.getX() - && epcLinkerFromObj.getDoubleValue("y") == epcLinkerPoint1.getY()){ // 从图形右侧侧出发 转换后 图形上侧出发 - bpmnLinkerFromObj.put("x",bpmnShapeFromProps.getDoubleValue("x") + (bpmnShapeFromProps.getDoubleValue("w") / 2)); - bpmnLinkerFromObj.put("y",bpmnShapeFromProps.getDoubleValue("y")); - bpmnLinkerFromObj.put("angle",LinkerDefConstant.ANGLE_DOWN); - bpmnLinkerToObj.put("x",bpmnShapeToProps.getDoubleValue("x") + (bpmnShapeToProps.getDoubleValue("w") / 2)); - bpmnLinkerToObj.put("y",bpmnShapeToProps.getDoubleValue("y")); - bpmnLinkerToObj.put("angle",LinkerDefConstant.ANGLE_DOWN); - - JSONObject point9 = new JSONObject(); - point9.put("x",epcLinkerPoint1.getY()); - point9.put("y",epcPageWidth - epcLinkerPoint1.getX()); - points.add(point9); - if (epcLinkerPoints.size() > 1){ - JSONObject point10 = new JSONObject(); - point10.put("x",epcLinkerPoint2.getY()); - point10.put("y",epcPageWidth - epcLinkerPoint2.getX()); - points.add(point10); - } - }else if (epcLinkerFromObj.getDoubleValue("x") > epcLinkerPoint1.getX() - && epcLinkerFromObj.getDoubleValue("y") == epcLinkerPoint1.getY()){ // 从图形左侧出发 转换后 图形下侧出发 - bpmnLinkerFromObj.put("x",bpmnShapeFromProps.getDoubleValue("x") + (bpmnShapeFromProps.getDoubleValue("w") / 2)); - bpmnLinkerFromObj.put("y",bpmnShapeFromProps.getDoubleValue("y") + bpmnShapeFromProps.getDoubleValue("h")); - bpmnLinkerFromObj.put("angle",LinkerDefConstant.ANGLE_UP); - bpmnLinkerToObj.put("x",bpmnShapeToProps.getDoubleValue("x") + (bpmnShapeToProps.getDoubleValue("w") / 2)); - bpmnLinkerToObj.put("y",bpmnShapeToProps.getDoubleValue("y") + bpmnShapeToProps.getDoubleValue("h")); - bpmnLinkerToObj.put("angle",LinkerDefConstant.ANGLE_UP); - - JSONObject point11 = new JSONObject(); - point11.put("x",epcLinkerPoint1.getY()); - point11.put("y",epcPageWidth - epcLinkerPoint1.getX()); - points.add(point11); - if (epcLinkerPoints.size() > 1){ - JSONObject point12 = new JSONObject(); - point12.put("x",epcLinkerPoint2.getY()); - point12.put("y",epcPageWidth - epcLinkerPoint2.getX()); - points.add(point12); - } - }else { - // 垂直方向上 - Map anchorPoiMap = ConvertUtil.getConvertAnchorPoi(elements, bpmnElements, epcLinkerObj); - if (anchorPoiMap.containsKey("from")){ - Position fromPoi = anchorPoiMap.get("from"); - bpmnLinkerFromObj.put("x",fromPoi.getX()); - bpmnLinkerFromObj.put("y",fromPoi.getY()); - } - List positionList = new ArrayList<>(); - positionList.add(new Position(bpmnLinkerFromObj.getDoubleValue("x"),bpmnLinkerFromObj.getDoubleValue("y"))); - for (Object o : epcLinkerPoints) { - JSONObject point = (JSONObject)o; - Position tempPoi = new Position(point.getDoubleValue("y"),epcPageWidth - point.getDoubleValue("x")); - positionList.add(tempPoi); - JSONObject tempPoint = new JSONObject(); - tempPoint.put("x",tempPoi.getX()); - tempPoint.put("y",tempPoi.getY()); - points.add(tempPoint); - } - if (anchorPoiMap.containsKey("to")){ - Position toPoi = anchorPoiMap.get("to"); - bpmnLinkerToObj.put("x",toPoi.getX()); - bpmnLinkerToObj.put("y",toPoi.getY()); - } - positionList.add(new Position(bpmnLinkerToObj.getDoubleValue("x"),bpmnLinkerToObj.getDoubleValue("y"))); - bpmnLinkerToObj.put("angle",ConvertUtil.getLinkerAngle(positionList,"to")); - bpmnLinkerFromObj.put("angle",ConvertUtil.getLinkerAngle(positionList,"from")); - } - } - JSONObject bpmnLinkerProps = new JSONObject(); - int zindex = zIndexMap.get("zindex").intValue(); - zIndexMap.put("zindex",zindex++); - bpmnLinkerProps.put("zindex",zindex++); - bpmnLinkerObj.put("props",bpmnLinkerProps); - bpmnLinkerObj.put("points",points); - bpmnLinkerObj.put("from",bpmnLinkerFromObj); - bpmnLinkerObj.put("to",bpmnLinkerToObj); - ConvertShapeIdMapping.getInstance().load(ConvertType.EPC_BPMN,key,bpmnLinkerDefId); - bpmnElements.put(bpmnLinkerDefId,bpmnLinkerObj); - }); - - // 1.3 增加开始 结束节点 - Map shapeYCountMap = new HashMap<>(); - List shapeYSet = new ArrayList<>(); - List shapeXSet = new ArrayList<>(); - bpmnElements.keySet().stream() - .filter(key -> !"linker".equals(bpmnElements.getJSONObject(key).getString("name"))) - .forEach(key -> { - JSONObject shapeProps = bpmnElements.getJSONObject(key).getJSONObject("props"); - Position shapePoi = new Position(shapeProps.getDoubleValue("x") + (shapeProps.getDoubleValue("w") / 2),shapeProps.getDoubleValue("y") + (shapeProps.getDoubleValue("h") / 2)); - shapeYSet.add(shapePoi.getY()); - shapeXSet.add(shapePoi.getX()); - }); - shapeYSet.stream().forEach(y -> { - if (shapeYCountMap.containsKey(y)){ - int value = shapeYCountMap.get(y).intValue() + 1; - shapeYCountMap.put(y,value); - }else { - shapeYCountMap.put(y,1); - } - }); - // 找到出现最多的中心点y值 一般来讲就是在整个水平的中轴线上 - double y = shapeYCountMap.entrySet().stream().sorted(new Comparator>() { - @Override - public int compare(Map.Entry o1, Map.Entry o2) { - return o2.getValue().intValue() - o1.getValue().intValue(); - } - }).map(entry -> entry.getKey()).findFirst().get(); - // 增加开始节点 - JSONObject startEventShapeDefinition = CoeDesignerUtil.getShapeDefinition(targetMethod, "startEvent"); - String startEventId = UUIDGener.getObjectId(); - startEventShapeDefinition.put("id",startEventId); - double startShapeX = 60.0 + epcPagePadding; - JSONObject startEventProps = startEventShapeDefinition.getJSONObject("props"); - double startShapeH = startEventProps.getDoubleValue("h"); - startEventProps.put("x",startShapeX); - startEventProps.put("y",y - (startShapeH / 2)); - startEventProps.put("angle","0"); - int zindex = zIndexMap.get("zindex").intValue(); - zIndexMap.put("zindex",zindex++); - startEventProps.put("zindex",zindex++); - startEventShapeDefinition.put("props",startEventProps); - this.handleDefaultProperty(startEventShapeDefinition); - bpmnElements.put(startEventId,startEventShapeDefinition); - // 增加结束节点 - Double endShapeX = shapeXSet.stream().max(Comparator.comparingDouble(Double::doubleValue)).get(); - JSONObject endEventShapeDefinition = CoeDesignerUtil.getShapeDefinition(targetMethod, "endEvent"); - String endEventId = UUIDGener.getObjectId(); - endEventShapeDefinition.put("id",endEventId); - JSONObject endEventProps = endEventShapeDefinition.getJSONObject("props"); - endEventProps.put("x",endShapeX + (endEventProps.getDoubleValue("w") / 2) + 100); - endEventProps.put("y",y - (startShapeH / 2)); - endEventProps.put("angle","0"); - int endZIndex = zIndexMap.get("zindex").intValue(); - zIndexMap.put("zindex",endZIndex++); - endEventProps.put("zindex",endZIndex++); - endEventShapeDefinition.put("props",endEventProps); - this.handleDefaultProperty(endEventShapeDefinition); - bpmnElements.put(endEventId,endEventShapeDefinition); + // 1.3 第二次循环 根据连线关系生成新的连线 + this.handleGenerateShapeLinker(elements,bpmnElements,zIndexMap,epcPageWidth); + // 1.4 增加开始 结束节点 // 存储事件节点 Map eventNodeMap = new HashMap<>(); Map>> linkerAdapterMap = new HashMap<>(); - - String eventMappingName = ConvertUtil.epcToBPMNShapeMapping("event"); - String annotation = ConvertUtil.epcToBPMNShapeMapping("procedure"); List annotationIds = new ArrayList<>(); - // Map eventShapeCenterPoiMap = new HashMap<>(); - List eventNodeList = new ArrayList<>(); - for (String key : bpmnElements.keySet()) { - JSONObject element = bpmnElements.getJSONObject(key); - String eleName = element.getString("name"); - if (annotation.equals(eleName)) annotationIds.add(element.getString("id")); - if (!eventMappingName.equals(eleName)) continue; - JSONObject props = element.getJSONObject("props"); - EventNode eventNode = new EventNode(key, props.getDoubleValue("x"), props.getDoubleValue("y"), props.getDoubleValue("w"), props.getDoubleValue("h")); - eventNodeList.add(eventNode); - - eventNodeMap.put(key,eventNode); - } - eventNodeList = eventNodeList.stream().sorted(new Comparator() { - @Override - public int compare(EventNode o1, EventNode o2) { - return (int) o1.getX() - (int)o2.getX(); - } - }).collect(Collectors.toList()); - // 1.4 开始节点/结束节点 与 开始事件/结束事件连线 - JSONObject startEventLinker = JSONObject.parseObject(LinkerDefConstant.linker); - String startEventLinkerId = UUIDGener.getObjectId(); - startEventLinker.put("id",startEventLinkerId); - JSONObject startEventLinkerFrom = new JSONObject(); - startEventLinkerFrom.put("id",startEventShapeDefinition.getString("id")); - startEventLinkerFrom.put("x",startEventProps.getDoubleValue("x") + startEventProps.getDoubleValue("w")); - startEventLinkerFrom.put("y",startEventProps.getDoubleValue("y") + (startEventProps.getDoubleValue("h") / 2)); - startEventLinkerFrom.put("angle",LinkerDefConstant.ANGLE_LEFT); - JSONObject startEventLinkerTo = new JSONObject(); - // 与产品沟通 转换前一定会有开始事件/结束事件 且在最两边 - EventNode startEpcEventNode = eventNodeList.get(0); - startEventLinkerTo.put("id",startEpcEventNode.getId()); - - int startEventLinkerZIndex = zIndexMap.get("zindex").intValue(); - JSONObject startEventLinkerProps = new JSONObject(); - zIndexMap.put("zindex",startEventLinkerZIndex++); - startEventLinkerProps.put("zindex",startEventLinkerZIndex++); - startEventLinker.put("props",startEventLinkerProps); - startEventLinker.put("from",startEventLinkerFrom); - - JSONArray startLinkerPoints = new JSONArray(); - if (startEventLinkerFrom.getDoubleValue("y") > startEventLinkerTo.getDoubleValue("y")){ - startEventLinkerTo.put("angle",LinkerDefConstant.ANGLE_UP); - startEventLinkerTo.put("x",startEpcEventNode.getX() + (startEpcEventNode.getWidth() / 2)); - startEventLinkerTo.put("y",startEpcEventNode.getY() + startEpcEventNode.getHeight()); - JSONObject point = new JSONObject(); - point.put("x",startEventLinkerTo.getDoubleValue("x")); - point.put("y",startEventLinkerFrom.getDoubleValue("y")); - startLinkerPoints.add(point); - }else if (startEventLinkerFrom.getDoubleValue("y") < startEventLinkerTo.getDoubleValue("y")){ - startEventLinkerTo.put("angle",LinkerDefConstant.ANGLE_DOWN); - startEventLinkerTo.put("x",startEpcEventNode.getX() + (startEpcEventNode.getWidth() / 2)); - startEventLinkerTo.put("y",startEpcEventNode.getY()); - JSONObject point = new JSONObject(); - point.put("x",startEventLinkerTo.getDoubleValue("x")); - point.put("y",startEventLinkerFrom.getDoubleValue("y")); - startLinkerPoints.add(point); - }else if (startEventLinkerFrom.getDoubleValue("y") == startEventLinkerTo.getDoubleValue("y")){ - startEventLinkerTo.put("angle",LinkerDefConstant.ANGLE_RIGHT); - startEventLinkerTo.put("x",startEpcEventNode.getX()); - startEventLinkerTo.put("y",startEpcEventNode.getY() + (startEpcEventNode.getWidth() / 2)); - JSONObject p1 = new JSONObject(); - p1.put("x",(startEventLinkerTo.getDoubleValue("x") - startEventLinkerFrom.getDoubleValue("x")) / 2); - p1.put("y",startEventLinkerFrom.getDoubleValue("y")); - startLinkerPoints.add(p1); - JSONObject p2 = new JSONObject(); - p2.put("x",(startEventLinkerTo.getDoubleValue("x") - startEventLinkerFrom.getDoubleValue("x")) / 2); - p2.put("y",startEventLinkerFrom.getDoubleValue("y")); - startLinkerPoints.add(p2); - } - startEventLinker.put("points",startLinkerPoints); - startEventLinker.put("to",startEventLinkerTo); - bpmnElements.put(startEventLinkerId,startEventLinker); - - JSONObject endEventLinker = JSONObject.parseObject(LinkerDefConstant.linker); - String endEventLinkerId = UUIDGener.getObjectId(); - endEventLinker.put("id",endEventLinkerId); - JSONObject endEventLinkerFrom = new JSONObject(); - EventNode endEpcEventNode = eventNodeList.get(eventNodeList.size() - 1); - endEventLinkerFrom.put("id",endEpcEventNode.getId()); - endEventLinkerFrom.put("x",endEpcEventNode.getCenterShapePosi().getX() + (endEpcEventNode.getWidth() / 2)); - endEventLinkerFrom.put("y",endEpcEventNode.getCenterShapePosi().getY()); - endEventLinkerFrom.put("angle",LinkerDefConstant.ANGLE_LEFT); - JSONObject endEventLinkerTo = new JSONObject(); - endEventLinkerTo.put("id",endEventShapeDefinition.getString("id")); - endEventLinkerTo.put("x",endEventProps.getDoubleValue("x")); - endEventLinkerTo.put("y",endEventProps.getDoubleValue("y") + (endEventProps.getDoubleValue("h") / 2)); - endEventLinker.put("angle",LinkerDefConstant.ANGLE_RIGHT); - int endEventLinkerZIndex = zIndexMap.get("zindex").intValue(); - JSONObject endEventLinkerProps = new JSONObject(); - zIndexMap.put("zindex",endEventLinkerZIndex++); - endEventLinkerProps.put("zindex",endEventLinkerZIndex++); - endEventLinker.put("props",endEventLinkerProps); - endEventLinker.put("from",endEventLinkerFrom); - endEventLinker.put("to",endEventLinkerTo); - bpmnElements.put(endEventLinkerId,endEventLinker); + this.handleStartAndEndNode(bpmnElements,zIndexMap,targetMethod,epcPagePadding,eventNodeMap,annotationIds); // 1.5 处理事件节点 图形变为线 Set toBeDeletes = new HashSet<>(); - eventNodeMap.keySet().stream().forEach(key -> { - EventNode eventNode = eventNodeMap.get(key); - bpmnElements.keySet().stream() - .filter(k -> "linker".equals(bpmnElements.getJSONObject(k).getString("name"))) - .forEach(k -> { - JSONObject linkerObj = bpmnElements.getJSONObject(k); - JSONObject fromObj = linkerObj.getJSONObject("from"); - JSONObject toObj = linkerObj.getJSONObject("to"); - JSONArray points = linkerObj.getJSONArray("points"); - // 找到从【事件】出去的线 进而找出【事件线】的to - if (eventNode.getId().equals(fromObj.getString("id"))){ - String toId = toObj.getString("id"); - if (!linkerAdapterMap.containsKey(key)){ - Map> map = new HashMap<>(); - List linkerAdapters = new ArrayList<>(); - map.put("to",linkerAdapters); - linkerAdapterMap.put(key,map); - } - Map> map = linkerAdapterMap.get(key); - if (!map.containsKey("to")){ - List linkerAdapters = new ArrayList<>(); - map.put("to",linkerAdapters); - } - List linkerAdapterList = map.get("to"); - Position position = new Position(toObj.getDoubleValue("x"),toObj.getDoubleValue("y")); - List pointList = new ArrayList<>(); - points.stream().forEach(item -> { - JSONObject point = (JSONObject) item; - Position poi = new Position(point.getDoubleValue("x"),point.getDoubleValue("y")); - pointList.add(poi); - }); - Position linkPoint = new Position(fromObj.getDoubleValue("x"),fromObj.getDoubleValue("y")); - LinkerAdapter linkerAdapter = new LinkerAdapter(toId,"to",position,pointList,linkPoint); - linkerAdapterList.add(linkerAdapter); - // 记录下待删除的连线的key - toBeDeletes.add(k); - }else if (eventNode.getId().equals(toObj.getString("id"))){ // 找到指向【事件】的线 进而找出【事件线】的from - String fromId = fromObj.getString("id"); - if (!linkerAdapterMap.containsKey(key)){ - Map> map = new HashMap<>(); - List linkerAdapters = new ArrayList<>(); - map.put("from",linkerAdapters); - linkerAdapterMap.put(key,map); - } - Map> map = linkerAdapterMap.get(key); - if (!map.containsKey("from")){ - List linkerAdapters = new ArrayList<>(); - map.put("from",linkerAdapters); - } - List linkerAdapterList = map.get("from"); - Position position = new Position(fromObj.getDoubleValue("x"),fromObj.getDoubleValue("y")); - List pointList = new ArrayList<>(); - points.stream().forEach(item -> { - JSONObject point = (JSONObject) item; - Position poi = new Position(point.getDoubleValue("x"),point.getDoubleValue("y")); - pointList.add(poi); - }); - Position linkPoint = new Position(toObj.getDoubleValue("x"),toObj.getDoubleValue("y")); - LinkerAdapter linkerAdapter = new LinkerAdapter(fromId,"from",position,pointList,linkPoint); - linkerAdapterList.add(linkerAdapter); - // 记录下待删除的连线的key - toBeDeletes.add(k); - } - }); - // 记录下待删除图形的key - toBeDeletes.add(key); - }); - - // 根据封装的LinkerAdapter生成新的linker 生成事件线 - for (String key : linkerAdapterMap.keySet()) { - EventNode eventNode = eventNodeMap.get(key); - String text = UtilString.isEmpty(bpmnElements.getJSONObject(eventNode.getId()).getString("text")) ? "事件" : bpmnElements.getJSONObject(eventNode.getId()).getString("text"); - Position centerShapePosi = eventNode.getCenterShapePosi(); - Map> listMap = linkerAdapterMap.get(key); - List fromLinkerList = listMap.get("from"); - List toLinkerList = listMap.get("to"); - if (!listMap.containsKey("from") || !listMap.containsKey("to")) { // 只有指出或者接收的线 - if (listMap.containsKey("to")){ // 没有指向event的线 - toLinkerList.stream().forEach(linkerAdapter -> { - Position toLinkerPosi = linkerAdapter.getPosition(); - JSONObject linkerDef = JSONObject.parseObject(LinkerDefConstant.linker); - String linkDefId = UUIDGener.getObjectId(); - linkerDef.put("id",linkDefId); - linkerDef.put("text",text); - linkerDef.put("points", ConvertUtil.getLinkerPoints(linkerAdapter.getPoints())); - JSONObject from = linkerDef.getJSONObject("from"); - from.put("x",centerShapePosi.getX()); - from.put("y",centerShapePosi.getY()); - linkerDef.put("from",from); - JSONObject to = linkerDef.getJSONObject("to"); - to.put("x",toLinkerPosi.getX()); - to.put("y",toLinkerPosi.getY()); - List positionList = new ArrayList<>(); - positionList.add(centerShapePosi); - if (linkerAdapter.getPoints().size() > 0) positionList.addAll(linkerAdapter.getPoints()); - positionList.add(toLinkerPosi); - to.put("angle",ConvertUtil.getLinkerAngle(positionList,"to")); - to.put("id",linkerAdapter.getId()); - linkerDef.put("to",to); - bpmnElements.put(linkDefId,linkerDef); - }); - }else if (listMap.containsKey("from")){ // 没有从event出发的线 - fromLinkerList.stream().forEach(linkerAdapter -> { - Position fromLinkPosi = linkerAdapter.getPosition(); - JSONObject linkerDef = JSONObject.parseObject(LinkerDefConstant.linker); - String linkDefId = UUIDGener.getObjectId(); - linkerDef.put("id",linkDefId); - linkerDef.put("text",text); - linkerDef.put("points",ConvertUtil.getLinkerPoints(linkerAdapter.getPoints())); - JSONObject from = linkerDef.getJSONObject("from"); - from.put("x",fromLinkPosi.getX()); - from.put("y",fromLinkPosi.getY()); - from.put("id",linkerAdapter.getId()); - List positionList = new ArrayList<>(); - positionList.add(fromLinkPosi); - if (linkerAdapter.getPoints().size() > 0) positionList.addAll(linkerAdapter.getPoints()); - positionList.add(centerShapePosi); - from.put("angle",ConvertUtil.getLinkerAngle(positionList,"from")); - linkerDef.put("from",from); - JSONObject to = linkerDef.getJSONObject("to"); - to.put("x",centerShapePosi.getX()); - to.put("y",centerShapePosi.getY()); - linkerDef.put("to",to); - bpmnElements.put(linkDefId,linkerDef); - }); - } - }else if (listMap.containsKey("from") && listMap.containsKey("to")){ - if (fromLinkerList.size() == 1 && toLinkerList.size() == 1){ - LinkerAdapter fromLinkerAdapter = fromLinkerList.get(0); - LinkerAdapter toLinkerAdapter = toLinkerList.get(0); - JSONObject linkerDef = JSONObject.parseObject(LinkerDefConstant.linker); - String linkDefId = UUIDGener.getObjectId(); - linkerDef.put("id",linkDefId); - linkerDef.put("text",text); - if (annotationIds.contains(fromLinkerAdapter.getId())){ - JSONObject lineStyle = linkerDef.getJSONObject("lineStyle"); - lineStyle.put("lineStyle","dashed"); - lineStyle.put("endArrowStyle","none"); - linkerDef.put("lineStyle",lineStyle); - } - List pointList = new ArrayList<>(); - if (fromLinkerAdapter.getPoints().size() > 0) pointList.addAll(fromLinkerAdapter.getPoints()); - // 判断当前事件节点是否要作为一个折点 - Position fromLinkPoint = fromLinkerAdapter.getLinkPoint(); - Position toLinkPoint = toLinkerAdapter.getLinkPoint(); - if (fromLinkPoint.getX() != toLinkPoint.getX() && fromLinkPoint.getY() != toLinkPoint.getY()){ - pointList.add(centerShapePosi); - } - if (toLinkerAdapter.getPoints().size() > 0) pointList.addAll(toLinkerAdapter.getPoints()); - linkerDef.put("points",ConvertUtil.getLinkerPoints(pointList)); - List allPosition = new ArrayList<>(); - allPosition.add(fromLinkerAdapter.getPosition()); - if (pointList.size() > 0) allPosition.addAll(pointList); - allPosition.add(toLinkerAdapter.getPosition()); - JSONObject from = linkerDef.getJSONObject("from"); - from.put("id",fromLinkerAdapter.getId()); - from.put("x",fromLinkerAdapter.getPosition().getX()); - from.put("y",fromLinkerAdapter.getPosition().getY()); - from.put("angle",ConvertUtil.getLinkerAngle(allPosition,"from")); - linkerDef.put("from",from); - JSONObject to = linkerDef.getJSONObject("to"); - to.put("id",toLinkerAdapter.getId()); - to.put("x",toLinkerAdapter.getPosition().getX()); - to.put("y",toLinkerAdapter.getPosition().getY()); - to.put("angle",ConvertUtil.getLinkerAngle(allPosition,"to")); - linkerDef.put("to",to); - bpmnElements.put(linkDefId,linkerDef); - }else if (fromLinkerList.size() > toLinkerList.size()){ - LinkerAdapter toLinkerAdapter = toLinkerList.get(0); - for (LinkerAdapter fromLinkerAdapter : fromLinkerList) { - JSONObject linkerDef = JSONObject.parseObject(LinkerDefConstant.linker); - String linkDefId = UUIDGener.getObjectId(); - linkerDef.put("id",linkDefId); - linkerDef.put("text",text); - // System.out.println("========>>>> " + annotationIds + " " + fromLinkerAdapter.getId()); - if (annotationIds.contains(fromLinkerAdapter.getId())){ - JSONObject lineStyle = linkerDef.getJSONObject("lineStyle"); - lineStyle.put("lineStyle","dashed"); - lineStyle.put("endArrowStyle","none"); - linkerDef.put("lineStyle",lineStyle); - } - List pointList = new ArrayList<>(); - if (fromLinkerAdapter.getPoints().size() > 0) pointList.addAll(fromLinkerAdapter.getPoints()); - // 判断当前事件节点是否要作为一个折点 - Position fromLinkPoint = fromLinkerAdapter.getLinkPoint(); - Position toLinkPoint = toLinkerAdapter.getLinkPoint(); - if (fromLinkPoint.getX() != toLinkPoint.getX() && fromLinkPoint.getY() != toLinkPoint.getY()){ - pointList.add(centerShapePosi); - } - if (toLinkerAdapter.getPoints().size() > 0) pointList.addAll(toLinkerAdapter.getPoints()); - linkerDef.put("points",ConvertUtil.getLinkerPoints(pointList)); - List allPosition = new ArrayList<>(); - allPosition.add(fromLinkerAdapter.getPosition()); - if (pointList.size() > 0) allPosition.addAll(pointList); - allPosition.add(toLinkerAdapter.getPosition()); - JSONObject from = linkerDef.getJSONObject("from"); - from.put("id",fromLinkerAdapter.getId()); - from.put("x",fromLinkerAdapter.getPosition().getX()); - from.put("y",fromLinkerAdapter.getPosition().getY()); - from.put("angle",ConvertUtil.getLinkerAngle(allPosition,"from")); - linkerDef.put("from",from); - JSONObject to = linkerDef.getJSONObject("to"); - to.put("id",toLinkerAdapter.getId()); - to.put("x",toLinkerAdapter.getPosition().getX()); - to.put("y",toLinkerAdapter.getPosition().getY()); - to.put("angle",ConvertUtil.getLinkerAngle(allPosition,"to")); - linkerDef.put("to",to); - bpmnElements.put(linkDefId,linkerDef); - } - } - } - } + this.handleEventNodeLinker(eventNodeMap,bpmnElements,linkerAdapterMap,toBeDeletes,annotationIds); // 1.6 删除待删除的节点 toBeDeletes.stream().forEach(key -> { @@ -839,7 +228,7 @@ public class EpcToBPMN implements ModelConvertStrategy { JSONObject bpmnDefineObj = JSONObject.parseObject(bpmnDefinition); bpmnDefineObj.put("elements",bpmnElements); JSONObject bpmnPage = bpmnDefineObj.getJSONObject("page"); - bpmnPage.put("width",epcPageHeight); + bpmnPage.put("width",maxX + 500); bpmnPage.put("height",epcPageWidth); bpmnDefineObj.put("page",bpmnPage); @@ -1124,4 +513,623 @@ public class EpcToBPMN implements ModelConvertStrategy { shapeDefinition.put("resizeable","1"); } } + + // 处理图形转换 + private void handleShapeConvert(JSONObject elements,JSONObject bpmnElements,Map zIndexMap,int epcPageWidth,String targetMethod){ + elements.keySet().stream().forEach(key -> { + JSONObject epcElement = elements.getJSONObject(key); + String shapeName = epcElement.getString("name"); + JSONObject props = epcElement.getJSONObject("props"); + // 处理图形 + if (!"linker".equals(shapeName)){ + // 记录当前EPC图形的中心点坐标 + double shapeCenterPoiX = props.getDoubleValue("x") + (props.getDoubleValue("w") / 2); + double shapeCenterPoiY = props.getDoubleValue("y") + (props.getDoubleValue("h") / 2); + Position epcShapePoi = new Position(shapeCenterPoiX, shapeCenterPoiY); + // 构建BPMN图形的中心点坐标 相当于向右旋转90度的效果 + Position bpmnShapeCenterPoi = new Position(shapeCenterPoiY, epcPageWidth - shapeCenterPoiX); + // 根据映射关系构建转换后的BPMN图形 + JSONObject shapeDefinition = CoeDesignerUtil.getShapeDefinition(targetMethod, ConvertUtil.epcToBPMNShapeMapping(shapeName)); + // 如果为空shapeDefinition可能是需求要求的图形映射关系不包含当前图形 + if (shapeDefinition != null){ + // 计算转后BPMN图形的起始坐标 + JSONObject propsObj = shapeDefinition.getJSONObject("props"); + double w = propsObj.getDoubleValue("w"); + double h = propsObj.getDoubleValue("h"); + double x = bpmnShapeCenterPoi.getX() - w / 2; + double y = bpmnShapeCenterPoi.getY() - h / 2; + propsObj.put("x",x); + propsObj.put("y",y); + int zindex = zIndexMap.get("zindex").intValue(); + zIndexMap.put("zindex",zindex++); + propsObj.put("zindex",zindex++); + propsObj.put("angle",props.getIntValue("angle")); + shapeDefinition.put("props",propsObj); + shapeDefinition.put("text",epcElement.getString("text")); + // 补充图形初始化结构的默认属性 + this.handleDefaultProperty(shapeDefinition); + // 记录下图形ID的映射关系 + String newShapeId = UUIDGener.getObjectId(); + shapeDefinition.put("id",newShapeId); + + ConvertShapeIdMapping.getInstance().load(ConvertType.EPC_BPMN,key,newShapeId); + + bpmnElements.put(newShapeId,shapeDefinition); + } + } + }); + } + + // 处理转换后的图形间距 + private double handleShapeSpace(JSONObject elements,JSONObject bpmnElements){ + double maxX = 0.0; + List linkerList = new ArrayList<>(); + for (String key : elements.keySet()) { + JSONObject element = elements.getJSONObject(key); + if (!"linker".equals(element.getString("name"))){ + continue; + } + JSONObject epcLinkerFromObj = element.getJSONObject("from"); + JSONObject epcLinkerToObj = element.getJSONObject("to"); + String epcLinkerFromId = epcLinkerFromObj.getString("id"); + String epcLinkerToId = epcLinkerToObj.getString("id"); + if (UtilString.isEmpty(epcLinkerFromId) && UtilString.isEmpty(epcLinkerToId)){ + continue; + } + // 转换前水平线过滤掉 + if (epcLinkerFromObj.getDoubleValue("y") == epcLinkerToObj.getDoubleValue("y")){ + continue; + } + linkerList.add(element); + } + linkerList = linkerList.stream().sorted(new Comparator() { + @Override + public int compare(JSONObject o1, JSONObject o2) { + JSONObject props1 = o1.getJSONObject("from"); + JSONObject props2 = o2.getJSONObject("from"); + if (props1.getDoubleValue("y") < props2.getDoubleValue("y")){ + return -1; + }else if (props1.getDoubleValue("y") > props2.getDoubleValue("y")){ + return 1; + }else { + return 0; + } + } + }).collect(Collectors.toList()); + + + List fromShapeId = new ArrayList<>(); + List toShapeId = new ArrayList<>(); + linkerList.stream().forEach(linkerObj -> { + JSONObject epcLinkerFromObj = linkerObj.getJSONObject("from"); + JSONObject epcLinkerToObj = linkerObj.getJSONObject("to"); + String epcLinkerFromId = epcLinkerFromObj.getString("id"); + String epcLinkerToId = epcLinkerToObj.getString("id"); + String bpmnFromShapeId = ConvertShapeIdMapping.getInstance().getTargetShapeId(ConvertType.EPC_BPMN, epcLinkerFromId); + String bpmnToShapeId = ConvertShapeIdMapping.getInstance().getTargetShapeId(ConvertType.EPC_BPMN, epcLinkerToId); + JSONObject bpmnFromShapeObj = bpmnElements.getJSONObject(bpmnFromShapeId); + JSONObject bpmnFromShapeProps = bpmnFromShapeObj.getJSONObject("props"); + JSONObject bpmnToShapeObj = bpmnElements.getJSONObject(bpmnToShapeId); + JSONObject bpmnToShapeProps = bpmnToShapeObj.getJSONObject("props"); + + Position bpmnFromShapeCenterPoi = new Position(bpmnFromShapeProps.getDoubleValue("x") + (bpmnFromShapeProps.getDoubleValue("w") / 2),bpmnFromShapeProps.getDoubleValue("y") + (bpmnFromShapeProps.getDoubleValue("h") / 2)); + Position bpmnToShapeCenterPoi = new Position(bpmnToShapeProps.getDoubleValue("x") + (bpmnToShapeProps.getDoubleValue("w") / 2),bpmnToShapeProps.getDoubleValue("y") + (bpmnToShapeProps.getDoubleValue("h") / 2)); + + if (bpmnToShapeCenterPoi.getX() < bpmnFromShapeCenterPoi.getX()){ + toShapeId.add(bpmnToShapeId); + } + }); + + // 根据排序后的连线处理图形间距 因为连线已经排序完毕 + // 所以正常来讲 都是被指向的图形向右移动 每个被指向的图形仅移动一次 + // 如果被指向的图形已经移动过 则考虑指向图形是否需要移动 + + for (JSONObject linker : linkerList) { + JSONObject epcLinkerFromObj = linker.getJSONObject("from"); + JSONObject epcLinkerToObj = linker.getJSONObject("to"); + String epcLinkerFromId = epcLinkerFromObj.getString("id"); + String epcLinkerToId = epcLinkerToObj.getString("id"); + String bpmnFromShapeId = ConvertShapeIdMapping.getInstance().getTargetShapeId(ConvertType.EPC_BPMN, epcLinkerFromId); + String bpmnToShapeId = ConvertShapeIdMapping.getInstance().getTargetShapeId(ConvertType.EPC_BPMN, epcLinkerToId); + JSONObject bpmnFromShapeObj = bpmnElements.getJSONObject(bpmnFromShapeId); + JSONObject bpmnFromShapeProps = bpmnFromShapeObj.getJSONObject("props"); + JSONObject bpmnToShapeObj = bpmnElements.getJSONObject(bpmnToShapeId); + JSONObject bpmnToShapeProps = bpmnToShapeObj.getJSONObject("props"); + + Position bpmnFromShapeCenterPoi = new Position(bpmnFromShapeProps.getDoubleValue("x") + (bpmnFromShapeProps.getDoubleValue("w") / 2),bpmnFromShapeProps.getDoubleValue("y") + (bpmnFromShapeProps.getDoubleValue("h") / 2)); + Position bpmnToShapeCenterPoi = new Position(bpmnToShapeProps.getDoubleValue("x") + (bpmnToShapeProps.getDoubleValue("w") / 2),bpmnToShapeProps.getDoubleValue("y") + (bpmnToShapeProps.getDoubleValue("h") / 2)); + + + if (bpmnToShapeCenterPoi.getX() >= bpmnFromShapeCenterPoi.getX()){ + double currentSpace = bpmnToShapeCenterPoi.getX() - bpmnFromShapeCenterPoi.getX(); // 当前间距 + double moveDistance = Math.ceil(ShapeConstant.EPC_TO_BPMN_SHAPE_SPACE - currentSpace); // 应该向右移动的距离 + double x = bpmnToShapeProps.getDoubleValue("x"); + bpmnToShapeProps.put("x",x + moveDistance); + bpmnToShapeObj.put("props",bpmnToShapeProps); + bpmnElements.put(bpmnToShapeId,bpmnToShapeObj); + + maxX = x + moveDistance > maxX ? x + moveDistance : maxX; + }else if (bpmnToShapeCenterPoi.getX() <= bpmnFromShapeCenterPoi.getX()){ + double currentSpace = bpmnFromShapeCenterPoi.getX() - bpmnToShapeCenterPoi.getX(); // 当前间距 + if (!toShapeId.contains(bpmnToShapeId)){ + double moveDistance = Math.ceil(ShapeConstant.EPC_TO_BPMN_SHAPE_SPACE + currentSpace); // 应该向右移动的距离 + double x = bpmnToShapeProps.getDoubleValue("x"); + bpmnToShapeProps.put("x",x + moveDistance); + bpmnToShapeObj.put("props",bpmnToShapeProps); + bpmnElements.put(bpmnToShapeId,bpmnToShapeObj); + + maxX = x + moveDistance > maxX ? x + moveDistance : maxX; + } + } + } + return maxX; + } + + // 处理生成新的连线 + private void handleGenerateShapeLinker(JSONObject elements,JSONObject bpmnElements,Map zIndexMap,int epcPageWidth){ + elements.keySet().stream() + .filter(key -> "linker".equals(elements.getJSONObject(key).getString("name"))) + .filter(key -> { + // 过滤掉既没有图形链接的线 + boolean flag = false; + JSONObject epcLinkerObj = elements.getJSONObject(key); + JSONObject epcLinkerFromObj = epcLinkerObj.getJSONObject("from"); + JSONObject epcLinkerToObj = epcLinkerObj.getJSONObject("to"); + String epcLinkerFromId = epcLinkerFromObj.getString("id"); + String epcLinkerToId = epcLinkerToObj.getString("id"); + if (UtilString.isNotEmpty(epcLinkerFromId) && UtilString.isNotEmpty(epcLinkerToId)){ + flag = true; + } + return flag; + }) + .forEach(key -> { + JSONObject epcLinkerObj = elements.getJSONObject(key); + JSONObject epcLinkerFromObj = epcLinkerObj.getJSONObject("from"); + JSONObject epcLinkerToObj = epcLinkerObj.getJSONObject("to"); + String epcLinkerFromId = epcLinkerFromObj.getString("id"); + Position epcLinkerFromPoi = new Position(epcLinkerFromObj.getDoubleValue("x"),epcLinkerFromObj.getDoubleValue("y")); + String epcLinkerToId = epcLinkerToObj.getString("id"); + Position epcLinkerToPoi = new Position(epcLinkerToObj.getDoubleValue("x"),epcLinkerToObj.getDoubleValue("y")); + JSONObject epcLinkerProps = epcLinkerObj.getJSONObject("props"); + JSONArray epcLinkerPoints = epcLinkerObj.getJSONArray("points"); + Position epcLinkerPoint1 = new Position(((JSONObject)epcLinkerPoints.get(0)).getDoubleValue("x"),((JSONObject)epcLinkerPoints.get(0)).getDoubleValue("y")); + Position epcLinkerPoint2 = null; + if (epcLinkerPoints.size() > 1){ + epcLinkerPoint2 = new Position(((JSONObject)epcLinkerPoints.get(1)).getDoubleValue("x"),((JSONObject)epcLinkerPoints.get(1)).getDoubleValue("y")); + } + + JSONObject bpmnLinkerObj = JSONObject.parseObject(LinkerDefConstant.linker); + String bpmnLinkerDefId = UUIDGener.getObjectId(); + String bpmnShapeFromId = ConvertShapeIdMapping.getInstance().getTargetShapeId(ConvertType.EPC_BPMN,epcLinkerFromId); + String bpmnShapeToId = ConvertShapeIdMapping.getInstance().getTargetShapeId(ConvertType.EPC_BPMN,epcLinkerToId); + bpmnLinkerObj.put("id",bpmnLinkerDefId); + bpmnLinkerObj.put("text",epcLinkerObj.getString("text")); + + JSONObject bpmnLinkerFromObj = new JSONObject(); + bpmnLinkerFromObj.put("id",bpmnShapeFromId); + JSONObject bpmnLinkerToObj = new JSONObject(); + bpmnLinkerToObj.put("id",bpmnShapeToId); + + JSONObject bpmnShapeFromObj = bpmnElements.getJSONObject(bpmnShapeFromId); + JSONObject bpmnShapeToObj = bpmnElements.getJSONObject(bpmnShapeToId); + + JSONObject bpmnShapeFromProps = bpmnShapeFromObj.getJSONObject("props"); + JSONObject bpmnShapeToProps = bpmnShapeToObj.getJSONObject("props"); + + JSONArray points = new JSONArray(); + Map convertLinkerTypeMap = new HashMap<>(); + Map anchorPoiMap = ConvertUtil.getConvertAnchorPoi(elements, bpmnElements, epcLinkerObj,convertLinkerTypeMap); + if (anchorPoiMap.containsKey("from")){ + Position fromPoi = anchorPoiMap.get("from"); + bpmnLinkerFromObj.put("x",fromPoi.getX()); + bpmnLinkerFromObj.put("y",fromPoi.getY()); + } + List positionList = new ArrayList<>(); + positionList.add(new Position(bpmnLinkerFromObj.getDoubleValue("x"),bpmnLinkerFromObj.getDoubleValue("y"))); + // 获取连线折点 + JSONArray linkerPoints = ConvertUtil.getLinkerPoints(convertLinkerTypeMap, anchorPoiMap, epcPageWidth); + if (linkerPoints != null){ + for (Object o : linkerPoints) { + JSONObject point = (JSONObject)o; + Position tempPoi = new Position(point.getDoubleValue("x"),point.getDoubleValue("y")); + positionList.add(tempPoi); + points.add(point); + } + } + if (anchorPoiMap.containsKey("to")){ + Position toPoi = anchorPoiMap.get("to"); + bpmnLinkerToObj.put("x",toPoi.getX()); + bpmnLinkerToObj.put("y",toPoi.getY()); + } + positionList.add(new Position(bpmnLinkerToObj.getDoubleValue("x"),bpmnLinkerToObj.getDoubleValue("y"))); + bpmnLinkerToObj.put("angle",ConvertUtil.getLinkerAngle(positionList,"to")); + bpmnLinkerFromObj.put("angle",ConvertUtil.getLinkerAngle(positionList,"from")); + JSONObject bpmnLinkerProps = new JSONObject(); + int zindex = zIndexMap.get("zindex").intValue(); + zIndexMap.put("zindex",zindex++); + bpmnLinkerProps.put("zindex",zindex++); + bpmnLinkerObj.put("props",bpmnLinkerProps); + bpmnLinkerObj.put("points",points); + bpmnLinkerObj.put("from",bpmnLinkerFromObj); + bpmnLinkerObj.put("to",bpmnLinkerToObj); + ConvertShapeIdMapping.getInstance().load(ConvertType.EPC_BPMN,key,bpmnLinkerDefId); + bpmnElements.put(bpmnLinkerDefId,bpmnLinkerObj); + }); + } + + // 处理开始节点结束节点 并连线 + private void handleStartAndEndNode(JSONObject bpmnElements,Map zIndexMap,String targetMethod,double epcPagePadding,Map eventNodeMap,List annotationIds){ + Map shapeYCountMap = new HashMap<>(); + List shapeYSet = new ArrayList<>(); + List shapeXSet = new ArrayList<>(); + bpmnElements.keySet().stream() + .filter(key -> !"linker".equals(bpmnElements.getJSONObject(key).getString("name"))) + .forEach(key -> { + JSONObject shapeProps = bpmnElements.getJSONObject(key).getJSONObject("props"); + Position shapePoi = new Position(shapeProps.getDoubleValue("x") + (shapeProps.getDoubleValue("w") / 2),shapeProps.getDoubleValue("y") + (shapeProps.getDoubleValue("h") / 2)); + shapeYSet.add(shapePoi.getY()); + shapeXSet.add(shapePoi.getX()); + }); + shapeYSet.stream().forEach(y -> { + if (shapeYCountMap.containsKey(y)){ + int value = shapeYCountMap.get(y).intValue() + 1; + shapeYCountMap.put(y,value); + }else { + shapeYCountMap.put(y,1); + } + }); + // 找到出现最多的中心点y值 一般来讲就是在整个水平的中轴线上 + double y = shapeYCountMap.entrySet().stream().sorted(new Comparator>() { + @Override + public int compare(Map.Entry o1, Map.Entry o2) { + return o2.getValue().intValue() - o1.getValue().intValue(); + } + }).map(entry -> entry.getKey()).findFirst().get(); + // 增加开始节点 + JSONObject startEventShapeDefinition = CoeDesignerUtil.getShapeDefinition(targetMethod, "startEvent"); + String startEventId = UUIDGener.getObjectId(); + startEventShapeDefinition.put("id",startEventId); + double startShapeX = 20.0 + epcPagePadding; + JSONObject startEventProps = startEventShapeDefinition.getJSONObject("props"); + double startShapeH = startEventProps.getDoubleValue("h"); + startEventProps.put("x",startShapeX); + startEventProps.put("y",y - (startShapeH / 2)); + startEventProps.put("angle","0"); + int zindex = zIndexMap.get("zindex").intValue(); + zIndexMap.put("zindex",zindex++); + startEventProps.put("zindex",zindex++); + startEventShapeDefinition.put("props",startEventProps); + this.handleDefaultProperty(startEventShapeDefinition); + bpmnElements.put(startEventId,startEventShapeDefinition); + // 增加结束节点 + Double endShapeX = shapeXSet.stream().max(Comparator.comparingDouble(Double::doubleValue)).get(); + JSONObject endEventShapeDefinition = CoeDesignerUtil.getShapeDefinition(targetMethod, "endEvent"); + String endEventId = UUIDGener.getObjectId(); + endEventShapeDefinition.put("id",endEventId); + JSONObject endEventProps = endEventShapeDefinition.getJSONObject("props"); + endEventProps.put("x",endShapeX + (endEventProps.getDoubleValue("w") / 2) + 100); + endEventProps.put("y",y - (startShapeH / 2)); + endEventProps.put("angle","0"); + int endZIndex = zIndexMap.get("zindex").intValue(); + zIndexMap.put("zindex",endZIndex++); + endEventProps.put("zindex",endZIndex++); + endEventShapeDefinition.put("props",endEventProps); + this.handleDefaultProperty(endEventShapeDefinition); + bpmnElements.put(endEventId,endEventShapeDefinition); + + String eventMappingName = ConvertUtil.epcToBPMNShapeMapping("event"); + String annotation = ConvertUtil.epcToBPMNShapeMapping("procedure"); + List eventNodeList = new ArrayList<>(); + for (String key : bpmnElements.keySet()) { + JSONObject element = bpmnElements.getJSONObject(key); + String eleName = element.getString("name"); + if (annotation.equals(eleName)) annotationIds.add(element.getString("id")); + if (!eventMappingName.equals(eleName)) continue; + JSONObject props = element.getJSONObject("props"); + EventNode eventNode = new EventNode(key, props.getDoubleValue("x"), props.getDoubleValue("y"), props.getDoubleValue("w"), props.getDoubleValue("h")); + eventNodeList.add(eventNode); + + eventNodeMap.put(key,eventNode); + } + eventNodeList = eventNodeList.stream().sorted(new Comparator() { + @Override + public int compare(EventNode o1, EventNode o2) { + return (int) o1.getX() - (int)o2.getX(); + } + }).collect(Collectors.toList()); + // 1.4 开始节点/结束节点 与 开始事件/结束事件连线 + JSONObject startEventLinker = JSONObject.parseObject(LinkerDefConstant.linker); + String startEventLinkerId = UUIDGener.getObjectId(); + startEventLinker.put("id",startEventLinkerId); + JSONObject startEventLinkerFrom = new JSONObject(); + startEventLinkerFrom.put("id",startEventShapeDefinition.getString("id")); + startEventLinkerFrom.put("x",startEventProps.getDoubleValue("x") + startEventProps.getDoubleValue("w")); + startEventLinkerFrom.put("y",startEventProps.getDoubleValue("y") + (startEventProps.getDoubleValue("h") / 2)); + startEventLinkerFrom.put("angle",LinkerDefConstant.ANGLE_LEFT); + JSONObject startEventLinkerTo = new JSONObject(); + // 与产品沟通 转换前一定会有开始事件/结束事件 且在最两边 + EventNode startEpcEventNode = eventNodeList.get(0); + startEventLinkerTo.put("id",startEpcEventNode.getId()); + + int startEventLinkerZIndex = zIndexMap.get("zindex").intValue(); + JSONObject startEventLinkerProps = new JSONObject(); + zIndexMap.put("zindex",startEventLinkerZIndex++); + startEventLinkerProps.put("zindex",startEventLinkerZIndex++); + startEventLinker.put("props",startEventLinkerProps); + startEventLinker.put("from",startEventLinkerFrom); + + // + JSONArray startLinkerPoints = new JSONArray(); + if (startEventLinkerFrom.getDoubleValue("y") > startEpcEventNode.getY() + startEpcEventNode.getHeight() / 2){ + startEventLinkerTo.put("angle",LinkerDefConstant.ANGLE_UP); + startEventLinkerTo.put("x",startEpcEventNode.getX() + (startEpcEventNode.getWidth() / 2)); + startEventLinkerTo.put("y",startEpcEventNode.getY() + startEpcEventNode.getHeight()); + JSONObject point = new JSONObject(); + point.put("x",startEventLinkerTo.getDoubleValue("x")); + point.put("y",startEventLinkerFrom.getDoubleValue("y")); + startLinkerPoints.add(point); + }else if (startEventLinkerFrom.getDoubleValue("y") < startEpcEventNode.getY() + startEpcEventNode.getHeight() / 2){ + startEventLinkerTo.put("angle",LinkerDefConstant.ANGLE_DOWN); + startEventLinkerTo.put("x",startEpcEventNode.getX() + (startEpcEventNode.getWidth() / 2)); + startEventLinkerTo.put("y",startEpcEventNode.getY()); + JSONObject point = new JSONObject(); + point.put("x",startEventLinkerTo.getDoubleValue("x")); + point.put("y",startEventLinkerFrom.getDoubleValue("y")); + startLinkerPoints.add(point); + }else if (startEventLinkerFrom.getDoubleValue("y") == startEpcEventNode.getY() + startEpcEventNode.getHeight() / 2){ + startEventLinkerTo.put("angle",LinkerDefConstant.ANGLE_RIGHT); + startEventLinkerTo.put("x",startEpcEventNode.getX()); + startEventLinkerTo.put("y",startEpcEventNode.getY() + (startEpcEventNode.getHeight() / 2)); + JSONObject p1 = new JSONObject(); + p1.put("x",startEventLinkerFrom.getDoubleValue("x") + (startEventLinkerTo.getDoubleValue("x") - startEventLinkerFrom.getDoubleValue("x")) / 2); + p1.put("y",startEventLinkerFrom.getDoubleValue("y")); + startLinkerPoints.add(p1); + JSONObject p2 = new JSONObject(); + p2.put("x",startEventLinkerFrom.getDoubleValue("x") + (startEventLinkerTo.getDoubleValue("x") - startEventLinkerFrom.getDoubleValue("x")) / 2); + p2.put("y",startEventLinkerFrom.getDoubleValue("y")); + startLinkerPoints.add(p2); + } + startEventLinker.put("points",startLinkerPoints); + startEventLinker.put("to",startEventLinkerTo); + bpmnElements.put(startEventLinkerId,startEventLinker); + + JSONObject endEventLinker = JSONObject.parseObject(LinkerDefConstant.linker); + String endEventLinkerId = UUIDGener.getObjectId(); + endEventLinker.put("id",endEventLinkerId); + JSONObject endEventLinkerFrom = new JSONObject(); + EventNode endEpcEventNode = eventNodeList.get(eventNodeList.size() - 1); + endEventLinkerFrom.put("id",endEpcEventNode.getId()); + endEventLinkerFrom.put("x",endEpcEventNode.getCenterShapePosi().getX() + (endEpcEventNode.getWidth() / 2)); + endEventLinkerFrom.put("y",endEpcEventNode.getCenterShapePosi().getY()); + endEventLinkerFrom.put("angle",LinkerDefConstant.ANGLE_LEFT); + JSONObject endEventLinkerTo = new JSONObject(); + endEventLinkerTo.put("id",endEventShapeDefinition.getString("id")); + endEventLinkerTo.put("x",endEventProps.getDoubleValue("x")); + endEventLinkerTo.put("y",endEventProps.getDoubleValue("y") + (endEventProps.getDoubleValue("h") / 2)); + endEventLinker.put("angle",LinkerDefConstant.ANGLE_RIGHT); + int endEventLinkerZIndex = zIndexMap.get("zindex").intValue(); + JSONObject endEventLinkerProps = new JSONObject(); + zIndexMap.put("zindex",endEventLinkerZIndex++); + endEventLinkerProps.put("zindex",endEventLinkerZIndex++); + endEventLinker.put("props",endEventLinkerProps); + endEventLinker.put("from",endEventLinkerFrom); + endEventLinker.put("to",endEventLinkerTo); + bpmnElements.put(endEventLinkerId,endEventLinker); + } + + // 处理事件节点转换为 连线 + private void handleEventNodeLinker(Map eventNodeMap,JSONObject bpmnElements,Map>> linkerAdapterMap,Set toBeDeletes,List annotationIds){ + eventNodeMap.keySet().stream().forEach(key -> { + EventNode eventNode = eventNodeMap.get(key); + bpmnElements.keySet().stream() + .filter(k -> "linker".equals(bpmnElements.getJSONObject(k).getString("name"))) + .forEach(k -> { + JSONObject linkerObj = bpmnElements.getJSONObject(k); + JSONObject fromObj = linkerObj.getJSONObject("from"); + JSONObject toObj = linkerObj.getJSONObject("to"); + JSONArray points = linkerObj.getJSONArray("points"); + // 找到从【事件】出去的线 进而找出【事件线】的to + if (eventNode.getId().equals(fromObj.getString("id"))){ + String toId = toObj.getString("id"); + if (!linkerAdapterMap.containsKey(key)){ + Map> map = new HashMap<>(); + List linkerAdapters = new ArrayList<>(); + map.put("to",linkerAdapters); + linkerAdapterMap.put(key,map); + } + Map> map = linkerAdapterMap.get(key); + if (!map.containsKey("to")){ + List linkerAdapters = new ArrayList<>(); + map.put("to",linkerAdapters); + } + List linkerAdapterList = map.get("to"); + Position position = new Position(toObj.getDoubleValue("x"),toObj.getDoubleValue("y")); + List pointList = new ArrayList<>(); + points.stream().forEach(item -> { + JSONObject point = (JSONObject) item; + Position poi = new Position(point.getDoubleValue("x"),point.getDoubleValue("y")); + pointList.add(poi); + }); + Position linkPoint = new Position(fromObj.getDoubleValue("x"),fromObj.getDoubleValue("y")); + LinkerAdapter linkerAdapter = new LinkerAdapter(toId,"to",position,pointList,linkPoint); + linkerAdapterList.add(linkerAdapter); + // 记录下待删除的连线的key + toBeDeletes.add(k); + }else if (eventNode.getId().equals(toObj.getString("id"))){ // 找到指向【事件】的线 进而找出【事件线】的from + String fromId = fromObj.getString("id"); + if (!linkerAdapterMap.containsKey(key)){ + Map> map = new HashMap<>(); + List linkerAdapters = new ArrayList<>(); + map.put("from",linkerAdapters); + linkerAdapterMap.put(key,map); + } + Map> map = linkerAdapterMap.get(key); + if (!map.containsKey("from")){ + List linkerAdapters = new ArrayList<>(); + map.put("from",linkerAdapters); + } + List linkerAdapterList = map.get("from"); + Position position = new Position(fromObj.getDoubleValue("x"),fromObj.getDoubleValue("y")); + List pointList = new ArrayList<>(); + points.stream().forEach(item -> { + JSONObject point = (JSONObject) item; + Position poi = new Position(point.getDoubleValue("x"),point.getDoubleValue("y")); + pointList.add(poi); + }); + Position linkPoint = new Position(toObj.getDoubleValue("x"),toObj.getDoubleValue("y")); + LinkerAdapter linkerAdapter = new LinkerAdapter(fromId,"from",position,pointList,linkPoint); + linkerAdapterList.add(linkerAdapter); + // 记录下待删除的连线的key + toBeDeletes.add(k); + } + }); + // 记录下待删除图形的key + toBeDeletes.add(key); + }); + + // 根据封装的LinkerAdapter生成新的linker 生成事件线 + for (String key : linkerAdapterMap.keySet()) { + EventNode eventNode = eventNodeMap.get(key); + String text = UtilString.isEmpty(bpmnElements.getJSONObject(eventNode.getId()).getString("text")) ? "事件" : bpmnElements.getJSONObject(eventNode.getId()).getString("text"); + Position centerShapePosi = eventNode.getCenterShapePosi(); + Map> listMap = linkerAdapterMap.get(key); + List fromLinkerList = listMap.get("from"); + List toLinkerList = listMap.get("to"); + if (!listMap.containsKey("from") || !listMap.containsKey("to")) { // 只有指出或者接收的线 + if (listMap.containsKey("to")){ // 没有指向event的线 + toLinkerList.stream().forEach(linkerAdapter -> { + Position toLinkerPosi = linkerAdapter.getPosition(); + JSONObject linkerDef = JSONObject.parseObject(LinkerDefConstant.linker); + String linkDefId = UUIDGener.getObjectId(); + linkerDef.put("id",linkDefId); + linkerDef.put("text",text); + linkerDef.put("points", ConvertUtil.getLinkerPoints(linkerAdapter.getPoints())); + JSONObject from = linkerDef.getJSONObject("from"); + from.put("x",centerShapePosi.getX()); + from.put("y",centerShapePosi.getY()); + linkerDef.put("from",from); + JSONObject to = linkerDef.getJSONObject("to"); + to.put("x",toLinkerPosi.getX()); + to.put("y",toLinkerPosi.getY()); + List positionList = new ArrayList<>(); + positionList.add(centerShapePosi); + if (linkerAdapter.getPoints().size() > 0) positionList.addAll(linkerAdapter.getPoints()); + positionList.add(toLinkerPosi); + to.put("angle",ConvertUtil.getLinkerAngle(positionList,"to")); + to.put("id",linkerAdapter.getId()); + linkerDef.put("to",to); + bpmnElements.put(linkDefId,linkerDef); + }); + }else if (listMap.containsKey("from")){ // 没有从event出发的线 + fromLinkerList.stream().forEach(linkerAdapter -> { + Position fromLinkPosi = linkerAdapter.getPosition(); + JSONObject linkerDef = JSONObject.parseObject(LinkerDefConstant.linker); + String linkDefId = UUIDGener.getObjectId(); + linkerDef.put("id",linkDefId); + linkerDef.put("text",text); + linkerDef.put("points",ConvertUtil.getLinkerPoints(linkerAdapter.getPoints())); + JSONObject from = linkerDef.getJSONObject("from"); + from.put("x",fromLinkPosi.getX()); + from.put("y",fromLinkPosi.getY()); + from.put("id",linkerAdapter.getId()); + List positionList = new ArrayList<>(); + positionList.add(fromLinkPosi); + if (linkerAdapter.getPoints().size() > 0) positionList.addAll(linkerAdapter.getPoints()); + positionList.add(centerShapePosi); + from.put("angle",ConvertUtil.getLinkerAngle(positionList,"from")); + linkerDef.put("from",from); + JSONObject to = linkerDef.getJSONObject("to"); + to.put("x",centerShapePosi.getX()); + to.put("y",centerShapePosi.getY()); + linkerDef.put("to",to); + bpmnElements.put(linkDefId,linkerDef); + }); + } + }else if (listMap.containsKey("from") && listMap.containsKey("to")){ + if (fromLinkerList.size() == 1 && toLinkerList.size() == 1){ + LinkerAdapter fromLinkerAdapter = fromLinkerList.get(0); + LinkerAdapter toLinkerAdapter = toLinkerList.get(0); + JSONObject linkerDef = JSONObject.parseObject(LinkerDefConstant.linker); + String linkDefId = UUIDGener.getObjectId(); + linkerDef.put("id",linkDefId); + linkerDef.put("text",text); + if (annotationIds.contains(fromLinkerAdapter.getId())){ + JSONObject lineStyle = linkerDef.getJSONObject("lineStyle"); + lineStyle.put("lineStyle","dashed"); + lineStyle.put("endArrowStyle","none"); + linkerDef.put("lineStyle",lineStyle); + } + List pointList = new ArrayList<>(); + if (fromLinkerAdapter.getPoints().size() > 0) pointList.addAll(fromLinkerAdapter.getPoints()); + // 判断当前事件节点是否要作为一个折点 + Position fromLinkPoint = fromLinkerAdapter.getLinkPoint(); + Position toLinkPoint = toLinkerAdapter.getLinkPoint(); + if (fromLinkPoint.getX() != toLinkPoint.getX() && fromLinkPoint.getY() != toLinkPoint.getY()){ + pointList.add(centerShapePosi); + } + if (toLinkerAdapter.getPoints().size() > 0) pointList.addAll(toLinkerAdapter.getPoints()); + linkerDef.put("points",ConvertUtil.getLinkerPoints(pointList)); + List allPosition = new ArrayList<>(); + allPosition.add(fromLinkerAdapter.getPosition()); + if (pointList.size() > 0) allPosition.addAll(pointList); + allPosition.add(toLinkerAdapter.getPosition()); + JSONObject from = linkerDef.getJSONObject("from"); + from.put("id",fromLinkerAdapter.getId()); + from.put("x",fromLinkerAdapter.getPosition().getX()); + from.put("y",fromLinkerAdapter.getPosition().getY()); + from.put("angle",ConvertUtil.getLinkerAngle(allPosition,"from")); + linkerDef.put("from",from); + JSONObject to = linkerDef.getJSONObject("to"); + to.put("id",toLinkerAdapter.getId()); + to.put("x",toLinkerAdapter.getPosition().getX()); + to.put("y",toLinkerAdapter.getPosition().getY()); + to.put("angle",ConvertUtil.getLinkerAngle(allPosition,"to")); + linkerDef.put("to",to); + bpmnElements.put(linkDefId,linkerDef); + }else if (fromLinkerList.size() > toLinkerList.size()){ + LinkerAdapter toLinkerAdapter = toLinkerList.get(0); + for (LinkerAdapter fromLinkerAdapter : fromLinkerList) { + JSONObject linkerDef = JSONObject.parseObject(LinkerDefConstant.linker); + String linkDefId = UUIDGener.getObjectId(); + linkerDef.put("id",linkDefId); + linkerDef.put("text",text); + // System.out.println("========>>>> " + annotationIds + " " + fromLinkerAdapter.getId()); + if (annotationIds.contains(fromLinkerAdapter.getId())){ + JSONObject lineStyle = linkerDef.getJSONObject("lineStyle"); + lineStyle.put("lineStyle","dashed"); + lineStyle.put("endArrowStyle","none"); + linkerDef.put("lineStyle",lineStyle); + } + List pointList = new ArrayList<>(); + if (fromLinkerAdapter.getPoints().size() > 0) pointList.addAll(fromLinkerAdapter.getPoints()); + // 判断当前事件节点是否要作为一个折点 + Position fromLinkPoint = fromLinkerAdapter.getLinkPoint(); + Position toLinkPoint = toLinkerAdapter.getLinkPoint(); + if (fromLinkPoint.getX() != toLinkPoint.getX() && fromLinkPoint.getY() != toLinkPoint.getY()){ + pointList.add(centerShapePosi); + } + if (toLinkerAdapter.getPoints().size() > 0) pointList.addAll(toLinkerAdapter.getPoints()); + linkerDef.put("points",ConvertUtil.getLinkerPoints(pointList)); + List allPosition = new ArrayList<>(); + allPosition.add(fromLinkerAdapter.getPosition()); + if (pointList.size() > 0) allPosition.addAll(pointList); + allPosition.add(toLinkerAdapter.getPosition()); + JSONObject from = linkerDef.getJSONObject("from"); + from.put("id",fromLinkerAdapter.getId()); + from.put("x",fromLinkerAdapter.getPosition().getX()); + from.put("y",fromLinkerAdapter.getPosition().getY()); + from.put("angle",ConvertUtil.getLinkerAngle(allPosition,"from")); + linkerDef.put("from",from); + JSONObject to = linkerDef.getJSONObject("to"); + to.put("id",toLinkerAdapter.getId()); + to.put("x",toLinkerAdapter.getPosition().getX()); + to.put("y",toLinkerAdapter.getPosition().getY()); + to.put("angle",ConvertUtil.getLinkerAngle(allPosition,"to")); + linkerDef.put("to",to); + bpmnElements.put(linkDefId,linkerDef); + } + } + } + } + } } diff --git a/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/util/ConvertUtil.java b/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/util/ConvertUtil.java index 691dceef..ad443746 100644 --- a/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/util/ConvertUtil.java +++ b/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/util/ConvertUtil.java @@ -3,6 +3,7 @@ package com.actionsoft.apps.coe.pal.modelconvert.util; import com.actionsoft.apps.coe.pal.modelconvert.cache.ConvertShapeIdMapping; import com.actionsoft.apps.coe.pal.modelconvert.constant.ConvertType; import com.actionsoft.apps.coe.pal.modelconvert.constant.LinkerDefConstant; +import com.actionsoft.apps.coe.pal.modelconvert.constant.ShapeConstant; import com.actionsoft.apps.coe.pal.modelconvert.model.Position; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; @@ -213,7 +214,7 @@ public class ConvertUtil { * @param beforeConvertLinker * @return */ - public static Map getConvertAnchorPoi(JSONObject beforeConvertElement,JSONObject afterConvertElement,JSONObject beforeConvertLinker){ + public static Map getConvertAnchorPoi(JSONObject beforeConvertElement,JSONObject afterConvertElement,JSONObject beforeConvertLinker,Map convertLinkerTypeMap){ Map resultMap = new HashMap<>(2); @@ -236,15 +237,42 @@ public class ConvertUtil { if (beforeConvertFromAnchorPoi.equals(leftFromPoi)){ // 转换前从左侧出 转换后从下侧出 Position afterBottomFromPoi = new Position(afterFromShapeProps.getDoubleValue("x") + (afterFromShapeProps.getDoubleValue("w") / 2),afterFromShapeProps.getDoubleValue("y") + afterFromShapeProps.getDoubleValue("h")); resultMap.put("from",afterBottomFromPoi); + convertLinkerTypeMap.put(ShapeConstant.LINKER_FROM_DIRECTION_KEY,"bottom"); }else if (beforeConvertFromAnchorPoi.equals(topFromPoi)){ // 转换前从上侧出 转换后从左侧出 Position afterLeftFromPoi = new Position(afterFromShapeProps.getDoubleValue("x"),afterFromShapeProps.getDoubleValue("y") + (afterFromShapeProps.getDoubleValue("h") / 2)); resultMap.put("from",afterLeftFromPoi); + convertLinkerTypeMap.put(ShapeConstant.LINKER_FROM_DIRECTION_KEY,"left"); }else if (beforeConvertFromAnchorPoi.equals(rightFromPoi)){ // 转换前从右侧出 转换后从上侧出 Position afterTopFromPoi = new Position(afterFromShapeProps.getDoubleValue("x") + (afterFromShapeProps.getDoubleValue("w") / 2),afterFromShapeProps.getDoubleValue("y")); resultMap.put("from",afterTopFromPoi); + convertLinkerTypeMap.put(ShapeConstant.LINKER_FROM_DIRECTION_KEY,"top"); }else if (beforeConvertFromAnchorPoi.equals(bottomFromPoi)){ // 转换前从下侧出 转换后从右侧出 Position afterRightFromPoi = new Position(afterFromShapeProps.getDoubleValue("x") + afterFromShapeProps.getDoubleValue("w"),afterFromShapeProps.getDoubleValue("y") + (afterFromShapeProps.getDoubleValue("h") / 2)); resultMap.put("from",afterRightFromPoi); + convertLinkerTypeMap.put(ShapeConstant.LINKER_FROM_DIRECTION_KEY,"right"); + }else{ + // 有坑 正常来讲不会进入这里 + if (beforeConvertFromAnchorPoi.getX() >= rightFromPoi.getX() && beforeConvertFromAnchorPoi.getY() > topFromPoi.getY() && beforeConvertFromAnchorPoi.getY() < bottomFromPoi.getY()){ + // 转换前从右侧出 转换后从上侧出 + Position afterTopFromPoi = new Position(afterFromShapeProps.getDoubleValue("x") + (afterFromShapeProps.getDoubleValue("w") / 2),afterFromShapeProps.getDoubleValue("y")); + resultMap.put("from",afterTopFromPoi); + convertLinkerTypeMap.put(ShapeConstant.LINKER_FROM_DIRECTION_KEY,"top"); + }else if (beforeConvertFromAnchorPoi.getX() <= leftFromPoi.getX() && beforeConvertFromAnchorPoi.getY() > topFromPoi.getY() && beforeConvertFromAnchorPoi.getY() < bottomFromPoi.getY()){ + // 转换前从左侧出 转换后从下侧出 + Position afterBottomFromPoi = new Position(afterFromShapeProps.getDoubleValue("x") + (afterFromShapeProps.getDoubleValue("w") / 2),afterFromShapeProps.getDoubleValue("y") + afterFromShapeProps.getDoubleValue("h")); + resultMap.put("from",afterBottomFromPoi); + convertLinkerTypeMap.put(ShapeConstant.LINKER_FROM_DIRECTION_KEY,"bottom"); + }else if (beforeConvertFromAnchorPoi.getX() > leftFromPoi.getX() && beforeConvertFromAnchorPoi.getX() < rightFromPoi.getX() && beforeConvertFromAnchorPoi.getY() <= topFromPoi.getY()){ + // 转换前从上侧出 转换后从左侧出 + Position afterLeftFromPoi = new Position(afterFromShapeProps.getDoubleValue("x"),afterFromShapeProps.getDoubleValue("y") + (afterFromShapeProps.getDoubleValue("h") / 2)); + resultMap.put("from",afterLeftFromPoi); + convertLinkerTypeMap.put(ShapeConstant.LINKER_FROM_DIRECTION_KEY,"left"); + }else if (beforeConvertFromAnchorPoi.getX() > leftFromPoi.getX() && beforeConvertFromAnchorPoi.getX() < rightFromPoi.getX() && beforeConvertFromAnchorPoi.getY() >= bottomFromPoi.getY()){ + // 转换前从下侧出 转换后从右侧出 + Position afterRightFromPoi = new Position(afterFromShapeProps.getDoubleValue("x") + afterFromShapeProps.getDoubleValue("w"),afterFromShapeProps.getDoubleValue("y") + (afterFromShapeProps.getDoubleValue("h") / 2)); + resultMap.put("from",afterRightFromPoi); + convertLinkerTypeMap.put(ShapeConstant.LINKER_FROM_DIRECTION_KEY,"right"); + } } }else { Position noneShape = new Position(linkerFromObj.getDoubleValue("y"),beforeConvertElement.getJSONObject("page").getDoubleValue("width") - linkerFromObj.getDoubleValue("x")); @@ -267,17 +295,44 @@ public class ConvertUtil { if (beforeConvertToAnchorPoi.equals(leftToPoi)){ // 转换前从左侧进入 转换后从下侧进入 Position afterBottomToPoi = new Position(afterToShapeProps.getDoubleValue("x") + (afterToShapeProps.getDoubleValue("w") / 2),afterToShapeProps.getDoubleValue("y") + afterToShapeProps.getDoubleValue("h")); resultMap.put("to",afterBottomToPoi); + convertLinkerTypeMap.put(ShapeConstant.LINKER_TO_DIRECTION_KEY,"bottom"); }else if (beforeConvertToAnchorPoi.equals(topToPoi)){ // 转换前从上侧进入 转换后从左侧进入 Position afterLeftToPoi = new Position(afterToShapeProps.getDoubleValue("x"),afterToShapeProps.getDoubleValue("y") + (afterToShapeProps.getDoubleValue("h") / 2)); resultMap.put("to",afterLeftToPoi); + convertLinkerTypeMap.put(ShapeConstant.LINKER_TO_DIRECTION_KEY,"left"); }else if (beforeConvertToAnchorPoi.equals(rightToPoi)){ // 转换前从右侧进入 转换后从上侧进入 Position afterTopToPoi = new Position(afterToShapeProps.getDoubleValue("x") + (afterToShapeProps.getDoubleValue("w") / 2),afterToShapeProps.getDoubleValue("y")); resultMap.put("to",afterTopToPoi); + convertLinkerTypeMap.put(ShapeConstant.LINKER_TO_DIRECTION_KEY,"top"); }else if (beforeConvertToAnchorPoi.equals(bottomToPoi)){ // 转换前从下侧进入 转换后从右侧进入 Position afterRightToPoi = new Position(afterToShapeProps.getDoubleValue("x") + afterToShapeProps.getDoubleValue("w"),afterToShapeProps.getDoubleValue("y") + (afterToShapeProps.getDoubleValue("h") / 2)); resultMap.put("to",afterRightToPoi); + convertLinkerTypeMap.put(ShapeConstant.LINKER_TO_DIRECTION_KEY,"right"); + }else { + // 有坑 正常来讲不会进入这里 + if (beforeConvertToAnchorPoi.getX() >= rightToPoi.getX() && beforeConvertToAnchorPoi.getY() > topToPoi.getY() && beforeConvertToAnchorPoi.getY() < bottomToPoi.getY()){ + // 转换前从右侧进入 转换后 从上侧进入 + Position afterTopToPoi = new Position(afterToShapeProps.getDoubleValue("x") + (afterToShapeProps.getDoubleValue("w") / 2),afterToShapeProps.getDoubleValue("y")); + resultMap.put("to",afterTopToPoi); + convertLinkerTypeMap.put(ShapeConstant.LINKER_TO_DIRECTION_KEY,"top"); + }else if (beforeConvertToAnchorPoi.getX() <= leftToPoi.getX() && beforeConvertToAnchorPoi.getY() > topToPoi.getY() && beforeConvertToAnchorPoi.getY() < bottomToPoi.getY()){ + // 转换前从左侧进入 转换后 从下侧进入 + Position afterBottomToPoi = new Position(afterToShapeProps.getDoubleValue("x") + (afterToShapeProps.getDoubleValue("w") / 2),afterToShapeProps.getDoubleValue("y") + afterToShapeProps.getDoubleValue("h")); + resultMap.put("to",afterBottomToPoi); + convertLinkerTypeMap.put(ShapeConstant.LINKER_TO_DIRECTION_KEY,"bottom"); + }else if (beforeConvertToAnchorPoi.getX() > leftToPoi.getX() && beforeConvertToAnchorPoi.getX() < rightToPoi.getX() && beforeConvertToAnchorPoi.getY() <= topToPoi.getY()){ + // 转换前从上侧进入 转换后 从左侧进入 + Position afterLeftToPoi = new Position(afterToShapeProps.getDoubleValue("x"),afterToShapeProps.getDoubleValue("y") + (afterToShapeProps.getDoubleValue("h") / 2)); + resultMap.put("to",afterLeftToPoi); + convertLinkerTypeMap.put(ShapeConstant.LINKER_TO_DIRECTION_KEY,"left"); + }else if (beforeConvertToAnchorPoi.getX() > leftToPoi.getX() && beforeConvertToAnchorPoi.getX() < rightToPoi.getX() && beforeConvertToAnchorPoi.getY() >= bottomToPoi.getY()){ + // 转换前从下侧进入 转换后 从右侧进入 + Position afterRightToPoi = new Position(afterToShapeProps.getDoubleValue("x") + afterToShapeProps.getDoubleValue("w"),afterToShapeProps.getDoubleValue("y") + (afterToShapeProps.getDoubleValue("h") / 2)); + resultMap.put("to",afterRightToPoi); + convertLinkerTypeMap.put(ShapeConstant.LINKER_TO_DIRECTION_KEY,"right"); + } } - }else { + }else { Position noneShape = new Position(linkerToObj.getDoubleValue("y"),beforeConvertElement.getJSONObject("page").getDoubleValue("width") - linkerToObj.getDoubleValue("x")); resultMap.put("to",noneShape); } @@ -285,4 +340,85 @@ public class ConvertUtil { return resultMap; } + + /** + * 获取图形转换后的连线折点【基于垂直向下方向 转向 水平向右方向的转换】 + * 【大概思路】连线折点大概有三种 + * 水平线折点为连线中点 + * 含有一个明显折点的连线 + * 含有两个明显折点的连线 + * @return + */ + public static JSONArray getLinkerPoints(Map convertLinkerTypeMap,Map anchorPoiMap,int pageHeight){ + + if (convertLinkerTypeMap.containsKey(ShapeConstant.LINKER_FROM_DIRECTION_KEY) && convertLinkerTypeMap.containsKey(ShapeConstant.LINKER_TO_DIRECTION_KEY)){ + JSONArray points = new JSONArray(); + Position fromPoi = anchorPoiMap.get("from"); + Position toPoi = anchorPoiMap.get("to"); + String fromDirection = convertLinkerTypeMap.get(ShapeConstant.LINKER_FROM_DIRECTION_KEY); + String toDirection = convertLinkerTypeMap.get(ShapeConstant.LINKER_TO_DIRECTION_KEY); + if ("right".equals(fromDirection) && "left".equals(toDirection)){ // 水平连线 + double x = (toPoi.getX() - fromPoi.getX()) / 2; + JSONObject p1 = new JSONObject(); + p1.put("x",fromPoi.getX() + x); + p1.put("y",fromPoi.getY()); + JSONObject p2 = new JSONObject(); + p2.put("x",fromPoi.getX() + x); + p2.put("y",fromPoi.getY()); + points.add(p1); + points.add(p2); + }else if ("left".equals(fromDirection) && "right".equals(toDirection)){ + double x = (fromPoi.getX() - toPoi.getX()) / 2; + JSONObject p1 = new JSONObject(); + p1.put("x",toPoi.getX() + x); + p1.put("y",toPoi.getY()); + JSONObject p2 = new JSONObject(); + p2.put("x",toPoi.getX() + x); + p2.put("y",toPoi.getY()); + points.add(p1); + points.add(p2); + }else if ("top".equals(fromDirection) && ("left".equals(toDirection) || "right".equals(toDirection))){ + JSONObject p = new JSONObject(); + p.put("x",fromPoi.getX()); + p.put("y",toPoi.getY()); + points.add(p); + }else if ("top".equals(toDirection) && ("left".equals(fromDirection) || "right".equals(fromDirection))){ + JSONObject p = new JSONObject(); + p.put("x",toPoi.getX()); + p.put("y",fromPoi.getY()); + points.add(p); + }else if ("bottom".equals(fromDirection) && ("left".equals(toDirection) || "right".equals(toDirection))){ + JSONObject p = new JSONObject(); + p.put("x",fromPoi.getX()); + p.put("y",toPoi.getY()); + points.add(p); + }else if ("bottom".equals(toDirection) && ("left".equals(fromDirection) || "right".equals(fromDirection))){ + JSONObject p = new JSONObject(); + p.put("x",toPoi.getX()); + p.put("y",fromPoi.getY()); + points.add(p); + }else if ("top".equals(fromDirection) && "top".equals(toDirection)){ + JSONObject p1 = new JSONObject(); + JSONObject p2 = new JSONObject(); + p1.put("x",fromPoi.getX()); + p1.put("y",100); + p2.put("x",toPoi.getX()); + p2.put("y",100); + points.add(p1); + points.add(p2); + }else if ("bottom".equals(fromDirection) && "bottom".equals(toDirection)){ + JSONObject p1 = new JSONObject(); + JSONObject p2 = new JSONObject(); + p1.put("x",fromPoi.getX()); + p1.put("y",pageHeight - 50); + p2.put("x",toPoi.getX()); + p2.put("y",pageHeight - 50); + points.add(p1); + points.add(p2); + } + return points; + } + return null; + } + }