From 74cc0cc6ddb2918fffb5590258cf2a1a35e8dffb Mon Sep 17 00:00:00 2001 From: qinoy Date: Mon, 12 Dec 2022 11:24:00 +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=BA=94=E7=94=A8=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20epc=E8=BD=ACbpmn?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...m.actionsoft.apps.coe.pal.modelconvert.jar | Bin 68069 -> 91725 bytes .../cache/ConvertShapeIdMapping.java | 24 +- .../modelconvert/constant/ConvertType.java | 4 +- .../coe/pal/modelconvert/model/Position.java | 16 + .../strategy/ModelConvertContext.java | 2 + .../attribute/impl/AwsOrgTypeAttrHandle.java | 14 +- .../impl/RelationTypeAttrHandle.java | 16 +- .../attribute/impl/TextTypeAttrHandle.java | 8 +- .../modelconvert/strategy/impl/EpcToBPMN.java | 1060 +++++++++++++++++ .../strategy/impl/EpcToFlowChart.java | 9 +- .../pal/modelconvert/util/ConvertUtil.java | 131 +- 11 files changed, 1252 insertions(+), 32 deletions(-) create mode 100644 com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/strategy/impl/EpcToBPMN.java 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 169fdf3e6357246190e62175eca27f44f546e26b..36c1ed204cd203afead0cc4ee141bb8990c7bc5e 100644 GIT binary patch delta 57325 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 delta 33958 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 diff --git a/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/cache/ConvertShapeIdMapping.java b/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/cache/ConvertShapeIdMapping.java index 369ea557..6d4dba2f 100644 --- a/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/cache/ConvertShapeIdMapping.java +++ b/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/cache/ConvertShapeIdMapping.java @@ -1,5 +1,7 @@ package com.actionsoft.apps.coe.pal.modelconvert.cache; +import com.actionsoft.apps.coe.pal.modelconvert.constant.ConvertType; + import java.util.HashMap; import java.util.Map; @@ -8,22 +10,30 @@ public class ConvertShapeIdMapping { private ConvertShapeIdMapping(){} private static ConvertShapeIdMapping convertShapeIdMapping = new ConvertShapeIdMapping(); // 存储被转换文件图形ID与转换后的文件图形ID的映射关系 - private static Map shapeIdMapping = new HashMap<>(); + private static Map> map = new HashMap<>(); + + private static Map epcToFlowChartShapeIdMapping = new HashMap<>(); + private static Map epcToBPMNShapeIdMapping = new HashMap<>(); + + static { + map.put(ConvertType.EPC_FLOWCHART,epcToFlowChartShapeIdMapping); + map.put(ConvertType.EPC_BPMN,epcToBPMNShapeIdMapping); + } public static ConvertShapeIdMapping getInstance(){ return convertShapeIdMapping; } - public void load(String sourceShapeId,String targetShapeId){ - shapeIdMapping.put(sourceShapeId,targetShapeId); + public void load(ConvertType type,String sourceShapeId,String targetShapeId){ + map.get(type).put(sourceShapeId,targetShapeId); } - public void clear(){ - shapeIdMapping.clear(); + public void clear(ConvertType type){ + map.get(type).clear(); } - public String getTargetShapeId(String sourceShapeId){ - return shapeIdMapping.get(sourceShapeId); + public String getTargetShapeId(ConvertType type,String sourceShapeId){ + return map.get(type).get(sourceShapeId); } } diff --git a/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/constant/ConvertType.java b/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/constant/ConvertType.java index 3c3aa96f..7dc3e135 100644 --- a/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/constant/ConvertType.java +++ b/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/constant/ConvertType.java @@ -3,8 +3,8 @@ package com.actionsoft.apps.coe.pal.modelconvert.constant; public enum ConvertType { EPC_FLOWCHART("process.epc","process.flowchart","EPC转FlowChart"), - EPC_BPMN("process.epc","process.bpmn","EPC转BPMN"), - FLOWCHART_BPMN("process.flowchart","process.bpmn","FlowChart转BPMN"); + EPC_BPMN("process.epc","process.bpmn2","EPC转BPMN"), + FLOWCHART_BPMN("process.flowchart","process.bpmn2","FlowChart转BPMN"); private ConvertType(String sourceMethod,String targetMethod,String desc){ this.sourceMethod = sourceMethod; diff --git a/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/model/Position.java b/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/model/Position.java index 094bbc8a..5b1b0b1a 100644 --- a/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/model/Position.java +++ b/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/model/Position.java @@ -1,5 +1,7 @@ package com.actionsoft.apps.coe.pal.modelconvert.model; +import java.util.Objects; + public class Position { private double x; private double y; @@ -16,4 +18,18 @@ public class Position { public double getY() { return y; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Position position = (Position) o; + return Double.compare(position.x, x) == 0 && + Double.compare(position.y, y) == 0; + } + + @Override + public int hashCode() { + return Objects.hash(x, y); + } } diff --git a/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/strategy/ModelConvertContext.java b/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/strategy/ModelConvertContext.java index 394c6b07..2d469dff 100644 --- a/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/strategy/ModelConvertContext.java +++ b/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/strategy/ModelConvertContext.java @@ -1,6 +1,7 @@ package com.actionsoft.apps.coe.pal.modelconvert.strategy; import com.actionsoft.apps.coe.pal.modelconvert.constant.ConvertType; +import com.actionsoft.apps.coe.pal.modelconvert.strategy.impl.EpcToBPMN; import com.actionsoft.apps.coe.pal.modelconvert.strategy.impl.EpcToFlowChart; import java.util.HashMap; @@ -14,6 +15,7 @@ public class ModelConvertContext { static { map.put(ConvertType.EPC_FLOWCHART,new EpcToFlowChart()); + map.put(ConvertType.EPC_BPMN,new EpcToBPMN()); } public static ModelConvertContext getInstance(){ diff --git a/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/strategy/attribute/impl/AwsOrgTypeAttrHandle.java b/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/strategy/attribute/impl/AwsOrgTypeAttrHandle.java index 92810584..7752cdfd 100644 --- a/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/strategy/attribute/impl/AwsOrgTypeAttrHandle.java +++ b/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/strategy/attribute/impl/AwsOrgTypeAttrHandle.java @@ -1,6 +1,7 @@ package com.actionsoft.apps.coe.pal.modelconvert.strategy.attribute.impl; 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.model.RelationAttributeModel; import com.actionsoft.apps.coe.pal.modelconvert.strategy.attribute.DataAttributeStrategy; import com.actionsoft.apps.coe.pal.pal.repository.dao.PALRepositoryPropertyDao; @@ -46,7 +47,7 @@ public class AwsOrgTypeAttrHandle implements DataAttributeStrategy { List sourceRelationModelList = shapeRelationDao.getModelListByFileId(sourceRepositoryId); // 关联类型的文件属性 关联表中 shapeId shapeText 字段是空值 sourceRelationModelList = sourceRelationModelList.stream() - .filter(model -> UtilString.isEmpty(model.getShapeId()) && UtilString.isEmpty(model.getShapeText())) + .filter(model -> UtilString.isEmpty(model.getShapeId())) .filter(model -> attrId.equals(model.getAttrId())) .filter(model -> "00000000-0000-0000-0000-000000000000".equals(model.getRelationFileId()) && "00000000-0000-0000-0000-000000000000".equals(model.getRelationShapeId())) .collect(Collectors.toList()); @@ -73,6 +74,7 @@ public class AwsOrgTypeAttrHandle implements DataAttributeStrategy { String targetRepositoryId = (String) param.get("targetRepositoryId"); String attrId = (String) param.get("attrId"); String beforeShapeName = (String) param.get("beforeShapeName"); + ConvertType convertType = (ConvertType) param.get("convertType"); // 1. definition 做处理 BaseModel baseModel = CoeDesignerAPIManager.getInstance().getDefinition(sourceRepositoryId, 0); String definition = baseModel.getDefinition(); @@ -100,7 +102,7 @@ public class AwsOrgTypeAttrHandle implements DataAttributeStrategy { String targetDefinition = CoeDesignerAPIManager.getInstance().getDefinition(targetRepositoryId, 0).getDefinition(); JSONObject targetDefineJsonObj = JSONObject.parseObject(targetDefinition); JSONObject targetElements = targetDefineJsonObj.getJSONObject("elements"); - JSONObject targetShape = targetElements.getJSONObject(ConvertShapeIdMapping.getInstance().getTargetShapeId(key)); + JSONObject targetShape = targetElements.getJSONObject(ConvertShapeIdMapping.getInstance().getTargetShapeId(convertType,key)); if (targetShape.containsKey("dataAttributes") && targetShape.getJSONArray("dataAttributes") != null){ JSONArray targetDataAttributes = targetShape.getJSONArray("dataAttributes"); for (int k = 0; k < targetDataAttributes.size(); k++) { @@ -109,7 +111,7 @@ public class AwsOrgTypeAttrHandle implements DataAttributeStrategy { JSONArray targetItemJSONArray = targetItem.getJSONArray("attributesJsonArray"); for (int l = 0; l < targetItemJSONArray.size(); l++) { JSONObject targetObj = targetItemJSONArray.getJSONObject(l); - if (targetObj == null) continue; + if (targetObj == null || targetObj.size() == 0) continue; if (targetObj.getString("id").equals(attrId) && "awsorg".equals(targetObj.getString("type"))) targetItemJSONArray.remove(l); } JSONObject tempObj = new JSONObject(); @@ -130,7 +132,7 @@ public class AwsOrgTypeAttrHandle implements DataAttributeStrategy { } } - targetElements.put(ConvertShapeIdMapping.getInstance().getTargetShapeId(key),targetShape); + targetElements.put(ConvertShapeIdMapping.getInstance().getTargetShapeId(convertType,key),targetShape); targetDefineJsonObj.put("elements",targetElements); BaseModel model = CoeDesignerAPIManager.getInstance().getDefinition(targetRepositoryId, 0); if (model == null) { @@ -157,12 +159,12 @@ public class AwsOrgTypeAttrHandle implements DataAttributeStrategy { .collect(Collectors.toList()); List result = new ArrayList<>(); for (DesignerShapeRelationModel relationModel : shapeRelationModelList) { - if (UtilString.isEmpty(ConvertShapeIdMapping.getInstance().getTargetShapeId(relationModel.getShapeId()))) { // 如果转换前为 事件 图形 直接跳过 + if (UtilString.isEmpty(ConvertShapeIdMapping.getInstance().getTargetShapeId(convertType,relationModel.getShapeId()))) { // 如果转换前为 事件 图形 直接跳过 continue; } relationModel.setId(UUIDGener.getUUID()); relationModel.setFileId(targetRepositoryId); - relationModel.setShapeId(ConvertShapeIdMapping.getInstance().getTargetShapeId(relationModel.getShapeId())); + relationModel.setShapeId(ConvertShapeIdMapping.getInstance().getTargetShapeId(convertType,relationModel.getShapeId())); relationModel.setShapeText(relationModel.getShapeText()); relationModel.setAttrId(relationModel.getAttrId()); relationModel.setRelationFileId(relationModel.getRelationFileId()); diff --git a/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/strategy/attribute/impl/RelationTypeAttrHandle.java b/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/strategy/attribute/impl/RelationTypeAttrHandle.java index 9da95fe3..7f8df707 100644 --- a/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/strategy/attribute/impl/RelationTypeAttrHandle.java +++ b/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/strategy/attribute/impl/RelationTypeAttrHandle.java @@ -1,6 +1,7 @@ package com.actionsoft.apps.coe.pal.modelconvert.strategy.attribute.impl; 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.model.RelationAttributeModel; import com.actionsoft.apps.coe.pal.modelconvert.strategy.attribute.DataAttributeStrategy; import com.actionsoft.apps.coe.pal.pal.repository.dao.PALRepositoryPropertyDao; @@ -51,7 +52,7 @@ public class RelationTypeAttrHandle implements DataAttributeStrategy { List sourceRelationModelList = shapeRelationDao.getModelListByFileId(sourceRepositoryId); // 关联类型的文件属性 关联表中 shapeId shapeText 字段是空值 sourceRelationModelList = sourceRelationModelList.stream() - .filter(model -> UtilString.isEmpty(model.getShapeId()) && UtilString.isEmpty(model.getShapeText())) + .filter(model -> UtilString.isEmpty(model.getShapeId())) .filter(model -> attrId.equals(model.getAttrId())) .filter(model -> !"00000000-0000-0000-0000-000000000000".equals(model.getRelationFileId()) && !"00000000-0000-0000-0000-000000000000".equals(model.getRelationShapeId())) .collect(Collectors.toList()); @@ -78,6 +79,7 @@ public class RelationTypeAttrHandle implements DataAttributeStrategy { String targetRepositoryId = (String) param.get("targetRepositoryId"); String attrId = (String) param.get("attrId"); String beforeShapeName = (String) param.get("beforeShapeName"); + ConvertType convertType = (ConvertType) param.get("convertType"); // 1. definition 做处理 BaseModel baseModel = CoeDesignerAPIManager.getInstance().getDefinition(sourceRepositoryId, 0); String definition = baseModel.getDefinition(); @@ -99,13 +101,13 @@ public class RelationTypeAttrHandle implements DataAttributeStrategy { JSONArray attributesJsonArray = item.getJSONArray("attributesJsonArray"); for (int j = 0; j < attributesJsonArray.size(); j++) { JSONObject object = attributesJsonArray.getJSONObject(j); - if (object == null) continue; + if (object == null || object.size() == 0) continue; if (object.getString("id").equals(attrId) && "relation".equals(object.getString("type"))){ // 将当前的属性存入到转换后的文件中 String targetDefinition = CoeDesignerAPIManager.getInstance().getDefinition(targetRepositoryId, 0).getDefinition(); JSONObject targetDefineJsonObj = JSONObject.parseObject(targetDefinition); JSONObject targetElements = targetDefineJsonObj.getJSONObject("elements"); - JSONObject targetShape = targetElements.getJSONObject(ConvertShapeIdMapping.getInstance().getTargetShapeId(key)); + JSONObject targetShape = targetElements.getJSONObject(ConvertShapeIdMapping.getInstance().getTargetShapeId(convertType,key)); if (targetShape.containsKey("dataAttributes") && targetShape.getJSONArray("dataAttributes") != null){ JSONArray targetDataAttributes = targetShape.getJSONArray("dataAttributes"); for (int k = 0; k < targetDataAttributes.size(); k++) { @@ -114,7 +116,7 @@ public class RelationTypeAttrHandle implements DataAttributeStrategy { JSONArray targetItemJSONArray = targetItem.getJSONArray("attributesJsonArray"); for (int l = 0; l < targetItemJSONArray.size(); l++) { JSONObject targetObj = targetItemJSONArray.getJSONObject(l); - if (targetObj == null) continue; + if (targetObj == null || targetObj.size() == 0) continue; if (targetObj.getString("id").equals(attrId) && "relation".equals(targetObj.getString("type"))) targetItemJSONArray.remove(l); } JSONObject tempObj = new JSONObject(); @@ -135,7 +137,7 @@ public class RelationTypeAttrHandle implements DataAttributeStrategy { } } - targetElements.put(ConvertShapeIdMapping.getInstance().getTargetShapeId(key),targetShape); + targetElements.put(ConvertShapeIdMapping.getInstance().getTargetShapeId(convertType,key),targetShape); targetDefineJsonObj.put("elements",targetElements); BaseModel model = CoeDesignerAPIManager.getInstance().getDefinition(targetRepositoryId, 0); if (model == null) { @@ -162,12 +164,12 @@ public class RelationTypeAttrHandle implements DataAttributeStrategy { .collect(Collectors.toList()); List result = new ArrayList<>(); for (DesignerShapeRelationModel relationModel : shapeRelationModelList) { - if (UtilString.isEmpty(ConvertShapeIdMapping.getInstance().getTargetShapeId(relationModel.getShapeId()))) { // 如果转换前为 事件 图形 直接跳过 + if (UtilString.isEmpty(ConvertShapeIdMapping.getInstance().getTargetShapeId(convertType,relationModel.getShapeId()))) { // 如果转换前为 事件 图形 直接跳过 continue; } relationModel.setId(UUIDGener.getUUID()); relationModel.setFileId(targetRepositoryId); - relationModel.setShapeId(ConvertShapeIdMapping.getInstance().getTargetShapeId(relationModel.getShapeId())); + relationModel.setShapeId(ConvertShapeIdMapping.getInstance().getTargetShapeId(convertType,relationModel.getShapeId())); relationModel.setShapeText(relationModel.getShapeText()); relationModel.setAttrId(relationModel.getAttrId()); relationModel.setRelationFileId(relationModel.getRelationFileId()); diff --git a/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/strategy/attribute/impl/TextTypeAttrHandle.java b/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/strategy/attribute/impl/TextTypeAttrHandle.java index 3f224743..140d2852 100644 --- a/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/strategy/attribute/impl/TextTypeAttrHandle.java +++ b/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/strategy/attribute/impl/TextTypeAttrHandle.java @@ -1,6 +1,7 @@ package com.actionsoft.apps.coe.pal.modelconvert.strategy.attribute.impl; 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.strategy.attribute.DataAttributeStrategy; import com.actionsoft.apps.coe.pal.pal.repository.dao.PALRepositoryPropertyDao; import com.actionsoft.apps.coe.pal.pal.repository.designer.manage.CoeDesignerAPIManager; @@ -50,6 +51,7 @@ public class TextTypeAttrHandle implements DataAttributeStrategy { String attrId = (String) param.get("attrId"); String beforeShapeName = (String) param.get("beforeShapeName"); String afterShapeName = (String) param.get("afterShapeName"); + ConvertType convertType = (ConvertType) param.get("convertType"); BaseModel baseModel = CoeDesignerAPIManager.getInstance().getDefinition(sourceRepositoryId, 0); String definition = baseModel.getDefinition(); JSONObject defineJsonObj = JSONObject.parseObject(definition); @@ -76,7 +78,7 @@ public class TextTypeAttrHandle implements DataAttributeStrategy { String targetDefinition = CoeDesignerAPIManager.getInstance().getDefinition(targetRepositoryId, 0).getDefinition(); JSONObject targetDefineJsonObj = JSONObject.parseObject(targetDefinition); JSONObject targetElements = targetDefineJsonObj.getJSONObject("elements"); - JSONObject targetShape = targetElements.getJSONObject(ConvertShapeIdMapping.getInstance().getTargetShapeId(key)); + JSONObject targetShape = targetElements.getJSONObject(ConvertShapeIdMapping.getInstance().getTargetShapeId(convertType,key)); if (targetShape.containsKey("dataAttributes") && targetShape.getJSONArray("dataAttributes") != null){ JSONArray targetDataAttributes = targetShape.getJSONArray("dataAttributes"); for (int k = 0; k < targetDataAttributes.size(); k++) { @@ -85,7 +87,7 @@ public class TextTypeAttrHandle implements DataAttributeStrategy { JSONArray targetItemJSONArray = targetItem.getJSONArray("attributesJsonArray"); for (int l = 0; l < targetItemJSONArray.size(); l++) { JSONObject targetObj = targetItemJSONArray.getJSONObject(l); - if (targetObj == null) continue; + if (targetObj == null || targetObj.size() == 0) continue; if (targetObj.getString("id").equals(attrId)) targetItemJSONArray.remove(l); } JSONObject tempObj = new JSONObject(); @@ -110,7 +112,7 @@ public class TextTypeAttrHandle implements DataAttributeStrategy { } } - targetElements.put(ConvertShapeIdMapping.getInstance().getTargetShapeId(key),targetShape); + targetElements.put(ConvertShapeIdMapping.getInstance().getTargetShapeId(convertType,key),targetShape); targetDefineJsonObj.put("elements",targetElements); BaseModel model = CoeDesignerAPIManager.getInstance().getDefinition(targetRepositoryId, 0); if (model == null) { diff --git a/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/strategy/impl/EpcToBPMN.java b/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/strategy/impl/EpcToBPMN.java new file mode 100644 index 00000000..aa04bfad --- /dev/null +++ b/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/strategy/impl/EpcToBPMN.java @@ -0,0 +1,1060 @@ +package com.actionsoft.apps.coe.pal.modelconvert.strategy.impl; + +import com.actionsoft.apps.coe.pal.constant.CoEConstant; +import com.actionsoft.apps.coe.pal.modelconvert.cache.ConvertShapeIdMapping; +import com.actionsoft.apps.coe.pal.modelconvert.cache.ConvertShapeNameMapping; +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.dao.HistoryRecordDao; +import com.actionsoft.apps.coe.pal.modelconvert.dao.HistoryRecordDetailDao; +import com.actionsoft.apps.coe.pal.modelconvert.model.*; +import com.actionsoft.apps.coe.pal.modelconvert.strategy.ModelConvertStrategy; +import com.actionsoft.apps.coe.pal.modelconvert.strategy.attribute.DataAttributeContext; +import com.actionsoft.apps.coe.pal.modelconvert.strategy.attribute.DataAttributeStrategy; +import com.actionsoft.apps.coe.pal.modelconvert.util.ConvertUtil; +import com.actionsoft.apps.coe.pal.pal.repository.dao.CoeProcessLevelDaoFacotory; +import com.actionsoft.apps.coe.pal.pal.repository.dao.PALRepository; +import com.actionsoft.apps.coe.pal.pal.repository.dao.PALRepositoryAttributeDao; +import com.actionsoft.apps.coe.pal.pal.repository.dao.PALRepositoryShapeAttributeDao; +import com.actionsoft.apps.coe.pal.pal.repository.designer.manage.CoeDesignerAPIManager; +import com.actionsoft.apps.coe.pal.pal.repository.designer.model.BaseModel; +import com.actionsoft.apps.coe.pal.pal.repository.designer.util.CoeDesignerUtil; +import com.actionsoft.apps.coe.pal.pal.repository.model.PALRepositoryAttributeModel; +import com.actionsoft.apps.coe.pal.pal.repository.model.PALRepositoryShapeAttributeModel; +import com.actionsoft.apps.coe.pal.pal.repository.model.impl.PALRepositoryModelImpl; +import com.actionsoft.apps.coe.pal.pal.repository.upfile.constant.CoeFileConstant; +import com.actionsoft.apps.coe.pal.pal.repository.upfile.dao.UpFileDao; +import com.actionsoft.apps.coe.pal.pal.repository.upfile.model.UpfileModel; +import com.actionsoft.apps.coe.pal.pal.repository.util.CoeProcessLevelUtil; +import com.actionsoft.apps.resource.plugin.profile.DCPluginProfile; +import com.actionsoft.bpms.server.UserContext; +import com.actionsoft.bpms.server.fs.DCContext; +import com.actionsoft.bpms.server.fs.dc.DCProfileManager; +import com.actionsoft.bpms.util.UUIDGener; +import com.actionsoft.bpms.util.UtilDate; +import com.actionsoft.bpms.util.UtilFile; +import com.actionsoft.bpms.util.UtilString; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; + +import java.sql.SQLException; +import java.sql.Timestamp; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.stream.Collectors; + +public class EpcToBPMN implements ModelConvertStrategy { + + @Override + public String modelConvert(UserContext uc, Map param) { + String epcModelId = (String) param.get("repositoryId"); + String sourceMethod = (String)param.get("sourceMethod"); + String targetMethod = (String)param.get("targetMethod"); + boolean duplicateName = Boolean.parseBoolean((String) param.get("duplicateName")); + PALRepository repository = CoeProcessLevelDaoFacotory.createCoeProcessLevel(); + PALRepositoryModelImpl epcRepositoryModel = (PALRepositoryModelImpl)repository.getInstance(epcModelId); + String bpmnModelId = UUIDGener.getUUID(); + String plRid = UUIDGener.getUUID(); + String parentId = epcRepositoryModel.getParentId(); + String wsId = epcRepositoryModel.getWsId(); + String methodCategory = targetMethod.substring(0,targetMethod.indexOf(".")); + int orderIndex = repository.getChildrenMaxOrderIndexByPidAndWsId(parentId, wsId) + 1; + Timestamp nowTime = new Timestamp(System.currentTimeMillis()); + String repositoryName = epcRepositoryModel.getName(); + PALRepositoryModelImpl repositoryModel = CoeProcessLevelUtil.createPALRepositoryModel(bpmnModelId, plRid, wsId, repositoryName, "", orderIndex, parentId, + methodCategory, true, 1, bpmnModelId, false, targetMethod, "0", epcRepositoryModel.getLevel(), null, null, + uc.getUID(), uc.getUID(), nowTime, null, null, null, null, null, null, null, null, null,epcRepositoryModel.getSecurityLevel()); + if (duplicateName) { + int count = epcRepositoryModel.getConvertCount(); + String suffix = "副本_" + count; + repositoryName += suffix; + repositoryModel.setName(repositoryName); + } + repository.updateConvertCount(epcRepositoryModel.getId()); + repository.insert(repositoryModel); + // 处理模型转换 + this.handleEPCToBPMN(epcModelId,bpmnModelId,targetMethod); + // 处理属性 + this.handleDataAttribute(epcModelId,bpmnModelId,wsId,sourceMethod,targetMethod); + // 处理附件 + this.handleRepositoryModelAttachment(uc,epcModelId,bpmnModelId); + // 历史记录表 + String historyId = UUIDGener.getUUID(); + HistoryRecord historyRecord = new HistoryRecord(); + historyRecord.setId(historyId); + historyRecord.setWsId(wsId); + historyRecord.setSourceMethod(sourceMethod); + historyRecord.setTargetMethod(targetMethod); + historyRecord.setOperator(uc.getUID()); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + Timestamp nowTimeStamp = UtilDate.parseTsFromDateTime(dateFormat.format(new Date())); + historyRecord.setOperationTime(nowTimeStamp); + HistoryRecordDao historyRecordDao = new HistoryRecordDao(); + historyRecordDao.insert(historyRecord); + // 历史记录详细 + HistoryRecordDetail recordDetail = new HistoryRecordDetail(); + recordDetail.setId(UUIDGener.getUUID()); + recordDetail.setHistoryRecordId(historyId); + recordDetail.setRepositoryId(epcRepositoryModel.getId()); + recordDetail.setRepositoryName(epcRepositoryModel.getName()); + HistoryRecordDetailDao detailDao = new HistoryRecordDetailDao(); + detailDao.insert(recordDetail); + return null; + } + + @Override + public String modelConvertBatch(UserContext uc, Map param) { + String repositoryIdListStr = (String) param.get("repositoryIdList"); + String[] repositoryIdList = repositoryIdListStr.split("#"); + String sourceMethod = (String)param.get("sourceMethod"); + String targetMethod = (String)param.get("targetMethod"); + boolean duplicateName = Boolean.parseBoolean((String) param.get("duplicateName")); + PALRepository repositoryDao = CoeProcessLevelDaoFacotory.createCoeProcessLevel(); + String wsId = ""; + for (String repositoryId : repositoryIdList) { + PALRepositoryModelImpl sourceRepositoryModel = (PALRepositoryModelImpl)repositoryDao.getInstance(repositoryId); + // 1. 入库 + String newRepositoryId = UUIDGener.getUUID(); + String plRid = UUIDGener.getUUID(); + String parentId = sourceRepositoryModel.getParentId(); + wsId = sourceRepositoryModel.getWsId(); + String methodCategory = targetMethod.substring(0,targetMethod.indexOf(".")); + int orderIndex = repositoryDao.getChildrenMaxOrderIndexByPidAndWsId(parentId, wsId) + 1; + Timestamp nowTime = new Timestamp(System.currentTimeMillis()); + String repositoryName = sourceRepositoryModel.getName(); + PALRepositoryModelImpl repositoryModel = CoeProcessLevelUtil.createPALRepositoryModel(newRepositoryId, plRid, wsId, repositoryName, "", orderIndex, parentId, + methodCategory, true, 1, newRepositoryId, false, targetMethod, "0", sourceRepositoryModel.getLevel(), null, null, + uc.getUID(), uc.getUID(), nowTime, null, null, null, null, null, null, null, null, null,sourceRepositoryModel.getSecurityLevel()); + if (duplicateName) { + int count = sourceRepositoryModel.getConvertCount(); + String suffix = "副本_" + count; + repositoryName += suffix; + repositoryModel.setName(repositoryName); + } + repositoryDao.updateConvertCount(sourceRepositoryModel.getId()); + repositoryDao.insert(repositoryModel); + // 2.调用模型转换的方法 + this.handleEPCToBPMN(repositoryId,newRepositoryId,targetMethod); + // 3.处理转换后的flowchart模型的文件属性 节点属性 形状显示规则 + this.handleDataAttribute(repositoryId,newRepositoryId,wsId,sourceMethod,targetMethod); + // 4. 处理附件 + this.handleRepositoryModelAttachment(uc,repositoryId,newRepositoryId); + } + // 5.1 历史记录表 + String historyId = UUIDGener.getUUID(); + HistoryRecord historyRecord = new HistoryRecord(); + historyRecord.setId(historyId); + historyRecord.setWsId(wsId); + historyRecord.setSourceMethod(sourceMethod); + historyRecord.setTargetMethod(targetMethod); + historyRecord.setOperator(uc.getUID()); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + Timestamp nowTimeStamp = UtilDate.parseTsFromDateTime(dateFormat.format(new Date())); + historyRecord.setOperationTime(nowTimeStamp); + HistoryRecordDao historyRecordDao = new HistoryRecordDao(); + historyRecordDao.insert(historyRecord); + // 5.2 历史记录详细 + List recordDetails = new ArrayList<>(); + for (String repositoryId : repositoryIdList) { + HistoryRecordDetail recordDetail = new HistoryRecordDetail(); + PALRepositoryModelImpl sourceRepositoryModel = (PALRepositoryModelImpl)repositoryDao.getInstance(repositoryId); + recordDetail.setId(UUIDGener.getUUID()); + recordDetail.setHistoryRecordId(historyId); + recordDetail.setRepositoryId(repositoryId); + recordDetail.setRepositoryName(sourceRepositoryModel.getName()); + recordDetails.add(recordDetail); + } + HistoryRecordDetailDao detailDao = new HistoryRecordDetailDao(); + try { + detailDao.batchInsert(recordDetails); + } catch (SQLException throwables) { + throwables.printStackTrace(); + } + return null; + } + + private void handleEPCToBPMN(String epcModelId,String bpmnModelId,String targetMethod){ + // 1.处理EPC模型中的数据 + BaseModel baseModel = CoeDesignerAPIManager.getInstance().getDefinition(epcModelId, 0); + String definition = baseModel.getDefinition(); + JSONObject defineJsonObj = JSONObject.parseObject(definition); + JSONObject epcPage = defineJsonObj.getJSONObject("page"); + double epcPagePadding = epcPage.getDoubleValue("padding"); + int epcPageWidth = epcPage.getIntValue("width"); + int epcPageHeight = epcPage.getIntValue("height"); + JSONObject elements = defineJsonObj.getJSONObject("elements"); + + ConvertShapeIdMapping.getInstance().clear(ConvertType.EPC_BPMN); + + Map zIndexMap = new HashMap<>(); + zIndexMap.put("zindex",1); + + JSONObject bpmnElements = new JSONObject(); + // 1.1 第一次循环 根据图形匹配规则生成新图形 位置不变 + 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); + } + } + }); + + // 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"); + Position epcLinkerPoint1 = new Position(((JSONObject)epcLinkerPoints.get(0)).getDoubleValue("x"),((JSONObject)epcLinkerPoints.get(0)).getDoubleValue("y")); + Position 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() + // && (epcLinkerFromObj.getDoubleValue("angle") == LinkerDefConstant.ANGLE_UP + // || epcLinkerFromObj.getDoubleValue("angle") == LinkerDefConstant.ANGLE_DOWN) + // && (epcLinkerToObj.getDoubleValue("angle") == LinkerDefConstant.ANGLE_UP + // || epcLinkerToObj.getDoubleValue("angle") == LinkerDefConstant.ANGLE_DOWN) + && 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() + // && (epcLinkerFromObj.getDoubleValue("angle") == LinkerDefConstant.ANGLE_LEFT + // || epcLinkerFromObj.getDoubleValue("angle") == LinkerDefConstant.ANGLE_RIGHT) + // && (epcLinkerToObj.getDoubleValue("angle") == LinkerDefConstant.ANGLE_LEFT + // || epcLinkerToObj.getDoubleValue("angle") == LinkerDefConstant.ANGLE_RIGHT) + && 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 { // 处理带明显折点的连线 + // System.out.println("==========================> "+epcLinkerObj.getString("text")); + // 根据angle值 来判断转换后的连线是在图形的上方还是下方 + 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(); + JSONObject point10 = new JSONObject(); + point9.put("x",epcLinkerPoint1.getY()); + point9.put("y",epcPageWidth - epcLinkerPoint1.getX()); + points.add(point9); + 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); + JSONObject point12 = new JSONObject(); + point12.put("x",epcLinkerPoint2.getY()); + point12.put("y",epcPageWidth - epcLinkerPoint2.getX()); + points.add(point12); + } + } + 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 = 10.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); + + // 存储事件节点 + Map eventNodeMap = new HashMap<>(); + Map>> linkerAdapterMap = new HashMap<>(); + + String eventMappingName = ConvertUtil.epcToBPMNShapeMapping("event"); + String annotation = ConvertUtil.epcToBPMNShapeMapping("procedure"); + String annotationId = ""; + // 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)) annotationId = 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()); + startEventLinkerTo.put("x",startEpcEventNode.getX()); + startEventLinkerTo.put("y",startEpcEventNode.getCenterShapePosi().getY()); + startEventLinkerTo.put("angle",LinkerDefConstant.ANGLE_RIGHT); + 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); + 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); + + + // 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); + 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","事件"); + 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","事件"); + 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","事件"); + 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","事件"); + if (annotationId.equals(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); + } + } + } + } + + // 1.6 删除待删除的节点 + toBeDeletes.stream().forEach(key -> { + if (bpmnElements.containsKey(key)){ + bpmnElements.remove(key); + } + }); + + // 2.根据处理好的数据生成BPMN模型 + BaseModel model = CoeDesignerAPIManager.getInstance().getDefinition(bpmnModelId, 0); + if (model == null) { + model = CoeDesignerUtil.createModel(bpmnModelId, 0); + } + String bpmnDefinition = model.getDefinition(); + JSONObject bpmnDefineObj = JSONObject.parseObject(bpmnDefinition); + bpmnDefineObj.put("elements",bpmnElements); + JSONObject bpmnPage = bpmnDefineObj.getJSONObject("page"); + bpmnPage.put("width",epcPageHeight); + bpmnPage.put("height",epcPageWidth); + bpmnDefineObj.put("page",bpmnPage); + + // 将ref引用的方法名替换为对应的代码 + String define = JSONObject.toJSONString(bpmnDefineObj); + Iterator iterator = ConvertUtil.getSchemaShapeMapping().keySet().iterator(); + while (iterator.hasNext()){ + String key = iterator.next(); + define = define.replace(key,ConvertUtil.getSchemaShapeMapping().get(key)); + } + + model.setDefinition(define); + CoeDesignerAPIManager.getInstance().storeDefinition(model); + } + + private void handleDataAttribute(String sourceRepositoryId,String targetRepositoryId,String wsId,String sourceMethod,String targetMethod){ + // 文件属性配置 + PALRepositoryAttributeDao fileAttrDao = new PALRepositoryAttributeDao(); + List sourceFileAttrList = fileAttrDao.getFileAttrConfigList(wsId, sourceMethod); + List targetFileAttrList = fileAttrDao.getFileAttrConfigList(wsId, targetMethod); + + sourceFileAttrList.stream().forEach(sourceFileAttr -> { + boolean targetFileAttrIsExist = targetFileAttrList.stream() + .anyMatch(targetFileAttr -> sourceFileAttr.getAttrId().equals(targetFileAttr.getAttrId()) + && sourceFileAttr.getType().equals(targetFileAttr.getType())); + if (targetFileAttrIsExist){ // 如果转换后的文件的建模属性中也有该属性配置 则将被转换的属性值导入过来 + // 文件属性值的处理 + DataAttributeStrategy attributeStrategy = DataAttributeContext.getInstance().dataAttributeStrategy(sourceFileAttr.getType()); + Map param = new HashMap<>(); + param.put("sourceRepositoryId",sourceRepositoryId); + param.put("targetRepositoryId",targetRepositoryId); + param.put("attrId",sourceFileAttr.getAttrId()); + param.put("convertType", ConvertType.EPC_BPMN); + attributeStrategy.fileAttrHandle(param); + } + }); + // 图形属性配置 + PALRepositoryShapeAttributeDao shapeAttrDao = new PALRepositoryShapeAttributeDao(); + List sourceShapeAttrList = shapeAttrDao.getShapeAttrConfigList(wsId, sourceMethod,""); + List targetShapeAttrList = shapeAttrDao.getShapeAttrConfigList(wsId, targetMethod,""); + sourceShapeAttrList.stream() + .filter(shapeAttr -> !ConvertUtil.epcToBPMNShapeMapping("event").equals(shapeAttr.getShapeName())) // 事件图形 直接跳过 + .filter(sourceShapeAttr -> UtilString.isNotEmpty(ConvertUtil.epcToBPMNShapeMapping(sourceShapeAttr.getShapeName()))) // 表中可能会存在一些历史脏数据 + .forEach(sourceShapeAttr -> { + boolean targetShapeAttrIsExist = targetShapeAttrList.stream() + .anyMatch(targetFileAttr -> sourceShapeAttr.getAttrId().equals(targetFileAttr.getAttrId()) + && sourceShapeAttr.getType().equals(targetFileAttr.getType()) + && ConvertUtil.epcToBPMNShapeMapping(sourceShapeAttr.getShapeName()).equals(targetFileAttr.getShapeName())); + if (targetShapeAttrIsExist){ // 如果转换后的文件的图形建模属性中也有该属性配置 则将被转换的属性值导入过来 + // 图形属性值的处理 + DataAttributeStrategy attributeStrategy = DataAttributeContext.getInstance().dataAttributeStrategy(sourceShapeAttr.getType()); + Map param = new HashMap<>(); + param.put("sourceRepositoryId",sourceRepositoryId); + param.put("targetRepositoryId",targetRepositoryId); + param.put("beforeShapeName",sourceShapeAttr.getShapeName()); + param.put("afterShapeName",ConvertUtil.epcToBPMNShapeMapping(sourceShapeAttr.getShapeName())); + param.put("attrId",sourceShapeAttr.getAttrId()); + param.put("convertType",ConvertType.EPC_BPMN); + attributeStrategy.shapeAttrHandle(param); + } + }); + } + + private void handleRepositoryModelAttachment(UserContext uc,String sourceRepositoryId, String targetRepositoryId){ + DCPluginProfile dcProfile = DCProfileManager.getDCProfile(CoEConstant.APP_ID, CoeFileConstant.COE_UPFILE); + UpFileDao upFileDao = new UpFileDao(); + // 查询模型附件 + List sourceModelFileList = upFileDao.searchByRepositoryId(sourceRepositoryId,"f"); + List targetFileList = new ArrayList<>(); + sourceModelFileList.stream().forEach(model -> { + // 封装附件实体 + UpfileModel upfileModel = new UpfileModel(); + upfileModel.setUuid(UUIDGener.getUUID()); + upfileModel.setPl_uuid(targetRepositoryId); + upfileModel.setShape_uuid(""); + upfileModel.setType(model.getType()); + upfileModel.setFileName(model.getFileName()); + upfileModel.setDownload(1); + upfileModel.setCreateUser(uc.getUID()); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + String dateStr = dateFormat.format(new Date()); + upfileModel.setCreateTime(UtilDate.parseTsFromDateTime(dateStr)); + upfileModel.setSecurityLevel(-1); + targetFileList.add(upfileModel); + // 处理DocCenter + DCContext fileDcContext = new DCContext(uc, dcProfile, CoEConstant.APP_ID, "file", model.getPl_uuid(), model.getFileName()); + String filePath = fileDcContext.getFilePath(); + UtilFile sourceFile = new UtilFile(filePath); + DCContext targetFileDcContext = new DCContext(uc, dcProfile, CoEConstant.APP_ID, "file", upfileModel.getPl_uuid(), upfileModel.getFileName()); + UtilFile targetFile = new UtilFile(targetFileDcContext.getFilePath()); + // 目标文件的父级目录 + UtilFile targetFileDir = new UtilFile(targetFileDcContext.getPath()); + try { + if (!targetFileDir.exists()){ + targetFileDir.mkdirs(); + } + if (!targetFile.exists()){ + targetFile.createNewFile(); + } + UtilFile.copyFile(sourceFile,targetFile); + } catch (Exception e) { + e.printStackTrace(); + } + }); + + // 模型中的图形附件 + List sourceShapeFileList = upFileDao.searchByRepositoryId(sourceRepositoryId,"s"); + sourceShapeFileList.stream().forEach(model -> { + UpfileModel upfileModel = new UpfileModel(); + upfileModel.setUuid(UUIDGener.getUUID()); + upfileModel.setPl_uuid(targetRepositoryId); + upfileModel.setShape_uuid(ConvertShapeIdMapping.getInstance().getTargetShapeId(ConvertType.EPC_BPMN,model.getShape_uuid())); + upfileModel.setType(model.getType()); + upfileModel.setFileName(model.getFileName()); + upfileModel.setDownload(1); + upfileModel.setCreateUser(uc.getUID()); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + String dateStr = dateFormat.format(new Date()); + upfileModel.setCreateTime(UtilDate.parseTsFromDateTime(dateStr)); + upfileModel.setSecurityLevel(-1); + targetFileList.add(upfileModel); + // 处理DocCenter + DCContext fileDcContext = new DCContext(uc, dcProfile, CoEConstant.APP_ID, model.getPl_uuid(), model.getShape_uuid(), model.getFileName()); + String filePath = fileDcContext.getFilePath(); + UtilFile sourceFile = new UtilFile(filePath); + DCContext targetFileDcContext = new DCContext(uc, dcProfile, CoEConstant.APP_ID, upfileModel.getPl_uuid(), upfileModel.getShape_uuid(), upfileModel.getFileName()); + UtilFile targetFile = new UtilFile(targetFileDcContext.getFilePath()); + // 目标文件的父级目录 + UtilFile targetFileDir = new UtilFile(targetFileDcContext.getPath()); + try { + if (!targetFileDir.exists()){ + targetFileDir.mkdirs(); + } + if (!targetFile.exists()){ + targetFile.createNewFile(); + } + UtilFile.copyFile(sourceFile,targetFile); + } catch (Exception e) { + e.printStackTrace(); + } + }); + upFileDao.batchInsert(targetFileList); + } + + // 补充图形初始化结构中的默认属性信息 + private void handleDefaultProperty(JSONObject shapeDefinition){ + // 补充初始化欠缺的属性 + if (!shapeDefinition.containsKey("locked")){ + shapeDefinition.put("locked",false); + } + if (!shapeDefinition.containsKey("link")){ + shapeDefinition.put("link",""); + } + if (!shapeDefinition.containsKey("children")){ + shapeDefinition.put("children",new JSONArray()); + } + if (!shapeDefinition.containsKey("parent")){ + shapeDefinition.put("parent",""); + } + if (!shapeDefinition.containsKey("orderIndex")){ + shapeDefinition.put("orderIndex",0); + } + if (!shapeDefinition.containsKey("attribute")){ + JSONObject attribute = new JSONObject(); + attribute.put("container",false); + attribute.put("visible",true); + attribute.put("rotatable",false); + attribute.put("linkable",true); + attribute.put("editable",true); + attribute.put("markerOffset",5); + shapeDefinition.put("attribute",attribute); + } + if (!shapeDefinition.containsKey("resizeDir")){ + JSONArray temp = new JSONArray(); + temp.add("tl"); + temp.add("tr"); + temp.add("br"); + temp.add("bl"); + shapeDefinition.put("resizeDir",temp); + } + if (!shapeDefinition.containsKey("dataAttributes")){ + JSONArray dataAttributes = new JSONArray(); + JSONObject attr = new JSONObject(); + attr.put("name","AWSProperties"); + attr.put("type","string"); + attr.put("value",""); + attr.put("category","default"); + attr.put("id","AWSPropertiesID"); + attr.put("linksArray",new JSONArray()); + attr.put("attributesContent",""); + attr.put("attributesJsonArray",new JSONArray()); + attr.put("privateAttribute",new JSONArray()); + attr.put("privateAttributeContent",new JSONArray()); + attr.put("privateShapesName",new JSONArray()); + attr.put("shapeGroupId",""); + attr.put("isCopy",""); + attr.put("shapeDesc",""); + attr.put("upFilesArray",new JSONArray()); + attr.put("relevanceShapes",new JSONArray()); + dataAttributes.add(attr); + shapeDefinition.put("dataAttributes",dataAttributes); + } + if (!shapeDefinition.containsKey("shapeStyle")){ + JSONObject shapeStyle = new JSONObject(); + shapeStyle.put("alpha",1); + shapeDefinition.put("shapeStyle",shapeStyle); + } + if (!shapeDefinition.containsKey("lineStyle")){ + JSONObject lineStyle = new JSONObject(); + lineStyle.put("lineWidth",1); + lineStyle.put("lineColor","50,50,50"); + lineStyle.put("lineStyle","solid"); + shapeDefinition.put("lineStyle",lineStyle); + }else { + JSONObject lineStyle = shapeDefinition.getJSONObject("lineStyle"); + if (!lineStyle.containsKey("lineWidth")){ + lineStyle.put("lineWidth",1); + } + if (!lineStyle.containsKey("lineStyle")){ + lineStyle.put("lineStyle","solid"); + } + if (!lineStyle.containsKey("lineColor")){ + lineStyle.put("lineColor","50,50,50"); + } + shapeDefinition.put("lineStyle",lineStyle); + } + if (!shapeDefinition.containsKey("fillStyle")){ + JSONObject fillStyle = new JSONObject(); + fillStyle.put("type","solid"); + fillStyle.put("color","255,255,255"); + shapeDefinition.put("fillStyle",fillStyle); + } + if (!shapeDefinition.containsKey("fontStyle")){ + JSONObject fontStyle = new JSONObject(); + fontStyle.put("fontFamily","Arial"); + fontStyle.put("size",14); + fontStyle.put("color","50,50,50"); + fontStyle.put("bold",false); + fontStyle.put("italic",false); + fontStyle.put("underline",false); + fontStyle.put("textAlign","center"); + fontStyle.put("vAlign","middle"); + fontStyle.put("orientation","vertical"); + shapeDefinition.put("fontStyle",fontStyle); + } + JSONArray anchors = new JSONArray(); + JSONObject anchor1 = new JSONObject(); + anchor1.put("x","w/2"); + anchor1.put("y","0"); + anchors.add(anchor1); + JSONObject anchor2 = new JSONObject(); + anchor2.put("x","w/2"); + anchor2.put("y","h"); + anchors.add(anchor2); + JSONObject anchor3 = new JSONObject(); + anchor3.put("x","0"); + anchor3.put("y","h/2"); + anchors.add(anchor3); + JSONObject anchor4 = new JSONObject(); + anchor4.put("x","w"); + anchor4.put("y","h/2"); + anchors.add(anchor4); + shapeDefinition.put("anchors",anchors); + + if (!shapeDefinition.containsKey("textBlock")){ + JSONObject textBlock = new JSONObject(); + textBlock.put("x","10"); + textBlock.put("y","0"); + textBlock.put("w","w-20"); + textBlock.put("h","h"); + shapeDefinition.put("textBlock",textBlock); + } + if (!shapeDefinition.containsKey("textBlockFinal")){ + JSONObject textBlockFinal = new JSONObject(); + textBlockFinal.put("x","w/2-60"); + textBlockFinal.put("y","h"); + textBlockFinal.put("w","120"); + textBlockFinal.put("h","30"); + shapeDefinition.put("textBlockFinal",textBlockFinal); + } + if (!shapeDefinition.containsKey("resizeable")){ + shapeDefinition.put("resizeable","1"); + } + } +} diff --git a/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/strategy/impl/EpcToFlowChart.java b/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/strategy/impl/EpcToFlowChart.java index 569d0566..afaf8275 100644 --- a/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/strategy/impl/EpcToFlowChart.java +++ b/com.actionsoft.apps.coe.pal.modelconvert/src/com/actionsoft/apps/coe/pal/modelconvert/strategy/impl/EpcToFlowChart.java @@ -4,6 +4,7 @@ import com.actionsoft.apps.coe.pal.constant.CoEConstant; import com.actionsoft.apps.coe.pal.modelconvert.cache.ConvertShapeIdMapping; import com.actionsoft.apps.coe.pal.modelconvert.cache.ConvertShapeNameMapping; import com.actionsoft.apps.coe.pal.modelconvert.cache.RepositoryModelCache; +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.dao.HistoryRecordDao; @@ -194,7 +195,7 @@ public class EpcToFlowChart implements ModelConvertStrategy { private void handleEPCToFlowChart(UserContext _uc,String repositoryId,String newRepositoryId,String targetMethodId){ // 每次转换前将存储的图形ID的映射关系清空 - ConvertShapeIdMapping.getInstance().clear(); + ConvertShapeIdMapping.getInstance().clear(ConvertType.EPC_FLOWCHART); // 3、根据当前EPC的define生成flowChart的define BaseModel baseModel = CoeDesignerAPIManager.getInstance().getDefinition(repositoryId, 0); @@ -253,7 +254,7 @@ public class EpcToFlowChart implements ModelConvertStrategy { toBeDeletes.add(key); // 存储一下转换前与转换后图形ID的映射关系 - ConvertShapeIdMapping.getInstance().load(key,_id); + ConvertShapeIdMapping.getInstance().load(ConvertType.EPC_FLOWCHART,key,_id); } if (!"linker".equals(shapeName)) { element.put("category",targetMethodId); @@ -262,7 +263,7 @@ public class EpcToFlowChart implements ModelConvertStrategy { // 除判断条件中的图形外 其他图形的ID转换前与转换后是一致的 因为总体上是在转换前的 definition 上进行改造 if (!("and".equals(shapeName) || "or".equals(shapeName) || "xor".equals(shapeName) || "event".equals(shapeName))){ - ConvertShapeIdMapping.getInstance().load(key,key); + ConvertShapeIdMapping.getInstance().load(ConvertType.EPC_FLOWCHART,key,key); } } }); @@ -545,6 +546,7 @@ public class EpcToFlowChart implements ModelConvertStrategy { param.put("sourceRepositoryId",sourceRepositoryId); param.put("targetRepositoryId",targetRepositoryId); param.put("attrId",sourceFileAttr.getAttrId()); + param.put("convertType",ConvertType.EPC_FLOWCHART); attributeStrategy.fileAttrHandle(param); } }); @@ -569,6 +571,7 @@ public class EpcToFlowChart implements ModelConvertStrategy { param.put("beforeShapeName",sourceShapeAttr.getShapeName()); param.put("afterShapeName",ConvertShapeNameMapping.getInstance().getShapeName(sourceShapeAttr.getShapeName())); param.put("attrId",sourceShapeAttr.getAttrId()); + param.put("convertType",ConvertType.EPC_FLOWCHART); attributeStrategy.shapeAttrHandle(param); } }); 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 8c7c758c..252d021f 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 @@ -6,13 +6,126 @@ import com.actionsoft.apps.coe.pal.modelconvert.model.Position; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; +import java.util.*; public class ConvertUtil { + private static String gateWay0Key = "{\"ref\":\"gateway0\"}"; + private static String gateWay0Value = "[{\"action\":\"move\", \"x\":\"0\", \"y\":\"h*0.5\"},{\"action\":\"line\", \"x\":\"w*0.5\", \"y\":\"0\"}," + + "{\"action\":\"line\", \"x\":\"w\", \"y\":\"h*0.5\"},{\"action\":\"line\", \"x\":\"w*0.5\", \"y\":\"h\"}," + + "{\"action\":\"line\", \"x\":\"0\", \"y\":\"h*0.5\"},{\"action\":\"close\"}]"; + + private static String roundKey = "{\"ref\":\"round\"}"; + private static String roundValue = "[{\"action\":\"move\",\"x\":\"0\",\"y\":\"h/2\"}," + + "{\"action\":\"curve\",\"x1\":\"0\",\"y1\":\"-h/6\",\"x2\":\"w\",\"y2\":\"-h/6\",\"x\":\"w\",\"y\":\"h/2\"}," + + "{\"action\":\"curve\",\"x1\":\"w\",\"y1\":\"h+h/6\",\"x2\":\"0\",\"y2\":\"h+h/6\",\"x\":\"0\",\"y\":\"h/2\"}," + + "{\"action\":\"close\"}]"; + + private static String roundRectangleKey = "{\"ref\":\"roundRectangle\"}"; + private static String roundRectangleValue = "[{\"action\":\"move\",\"x\":\"0\",\"y\":\"4\"}," + + "{\"action\":\"quadraticCurve\",\"x1\":\"0\",\"y1\":\"0\",\"x\":\"4\",\"y\":\"0\"}," + + "{\"action\":\"line\",\"x\":\"w-4\",\"y\":\"0\"}," + + "{\"action\":\"quadraticCurve\",\"x1\":\"w\",\"y1\":\"0\",\"x\":\"w\",\"y\":\"4\"}," + + "{\"action\":\"line\",\"x\":\"w\",\"y\":\"h-4\"}," + + "{\"action\":\"quadraticCurve\",\"x1\":\"w\",\"y1\":\"h\",\"x\":\"w-4\",\"y\":\"h\"}," + + "{\"action\":\"line\",\"x\":\"4\",\"y\":\"h\"}," + + "{\"action\":\"quadraticCurve\",\"x1\":\"0\",\"y1\":\"h\",\"x\":\"0\",\"y\":\"h-4\"}," + + "{\"action\":\"close\"}]"; + + private static String scriptTaskKey = "{\"ref\":\"script_task\"}"; + private static String scriptTaskValue = "[{\"action\":\"move\", \"x\":\"100*0.15- 100*0.05\", \"y\":\"60*0.24- 60*0.1\"},\n" + + " {\"action\":\"line\", \"x\":\"100*0.15 + 100*0.05\", \"y\":\"60*0.24 - 60*0.1\"},\n" + + " {\"action\":\"curve\", \"x1\":\"100*0.15 + 100*0.02\", \"y1\":\"60*0.24 - 60*0.1\", \"x2\":\"100*0.15 + 100*0.02\", \"y2\":\"60*0.24\", \"x\":\"100*0.15 + 100*0.04\", \"y\":\"60*0.24\"},\n" + + " {\"action\":\"curve\", \"x1\":\"100*0.15 + 100*0.06\", \"y1\":\"60*0.24\", \"x2\":\"100*0.15 + 100*0.06\", \"y2\":\"60*0.24 + 60*0.1\", \"x\":\"100*0.15 + 100*0.03\", \"y\":\"60*0.24 + 60*0.1\"},\n" + + " {\"action\":\"line\", \"x\":\"100*0.15 - 100*0.08\", \"y\":\"60*0.24 + 60*0.1\"},\n" + + " {\"action\":\"curve\", \"x1\":\"100*0.15 - 100*0.05\", \"y1\":\"60*0.24 + 60*0.1\", \"x2\":\"100*0.15 - 100*0.05\", \"y2\":\"60*0.24\", \"x\":\"100*0.15 - 100*0.07\", \"y\":\"60*0.24\"},\n" + + " {\"action\":\"curve\", \"x1\":\"100*0.15 - 100*0.09\", \"y1\":\"60*0.24\", \"x2\":\"100*0.15 - 100*0.09\", \"y2\":\"60*0.24 - 60*0.1\", \"x\":\"100*0.15 - 100*0.05\", \"y\":\"60*0.24 - 60*0.1\"},\n" + + " {\"action\":\"close\"},\n" + + " {\"action\":\"move\", \"x\":\"100*0.15 - 100*0.08\", \"y\":\"60*0.24 - 60*0.05\"},\n" + + " {\"action\":\"line\", \"x\":\"100*0.15 + 100*0.025\", \"y\":\"60*0.24 - 60*0.05\"},\n" + + " {\"action\":\"move\", \"x\":\"100*0.15 - 100*0.07\", \"y\":\"60*0.24 - 0\"},\n" + + " {\"action\":\"line\", \"x\":\"100*0.15 + 100*0.04\", \"y\":\"60*0.24 - 0\"},\n" + + " {\"action\":\"move\", \"x\":\"100*0.15 - 100*0.055\", \"y\":\"60*0.24 + 60*0.06\"},\n" + + " {\"action\":\"line\", \"x\":\"100*0.15 + 100*0.05\", \"y\":\"60*0.24 + 60*0.06\"}]"; + + private static String manualTaskKey = "{\"ref\":\"manual_task\"}"; + private static String manualTaskValue = "[{\"action\":\"move\", \"x\":\"100*0.15- 100*0.08\", \"y\":\"60*0.2\"},\n" + + " {\"action\":\"line\", \"x\":\"100*0.15- 100*0.04\", \"y\":\"60*0.2\"},\n" + + " {\"action\":\"line\", \"x\":\"100*0.15+ 100*0.01\", \"y\":\"60*0.13\"},\n" + + " {\"action\":\"line\", \"x\":\"100*0.15+ 100*0.04\", \"y\":\"60*0.13\"},\n" + + " {\"action\":\"line\", \"x\":\"100*0.15 + 100*0.04\", \"y\":\"60*0.17\"},\n" + + " {\"action\":\"line\", \"x\":\"100*0.15+ 100*0.01\", \"y\":\"60*0.17\"},\n" + + " {\"action\":\"line\", \"x\":\"100*0.15+ 100*0.1\", \"y\":\"60*0.17\"},\n" + + " {\"action\":\"line\", \"x\":\"100*0.15+ 100*0.1\", \"y\":\"60*0.21\"},\n" + + " {\"action\":\"line\", \"x\":\"100*0.15+ 100*0.01\", \"y\":\"60*0.21\"},\n" + + " {\"action\":\"line\", \"x\":\"100*0.15+ 100*0.06\", \"y\":\"60*0.21\"},\n" + + " {\"action\":\"line\", \"x\":\"100*0.15+ 100*0.06\", \"y\":\"60*0.25\"},\n" + + " {\"action\":\"line\", \"x\":\"100*0.15+ 100*0.01\", \"y\":\"60*0.25\"},\n" + + " {\"action\":\"line\", \"x\":\"100*0.15+ 100*0.06\", \"y\":\"60*0.25\"},\n" + + " {\"action\":\"line\", \"x\":\"100*0.15+ 100*0.06\", \"y\":\"60*0.29\"},\n" + + " {\"action\":\"line\", \"x\":\"100*0.15+ 100*0.06\", \"y\":\"60*0.29\"},\n" + + " {\"action\":\"line\", \"x\":\"100*0.15+ 100*0.04\", \"y\":\"60*0.29\"},\n" + + " {\"action\":\"line\", \"x\":\"100*0.15+ 100*0.04\", \"y\":\"60*0.33\"},\n" + + " {\"action\":\"line\", \"x\":\"100*0.15- 100*0.04\", \"y\":\"60*0.33\"},\n" + + " {\"action\":\"line\", \"x\":\"100*0.15- 100*0.08\", \"y\":\"60*0.28\"},\n" + + " {\"action\":\"line\", \"x\":\"100*0.15- 100*0.08\", \"y\":\"60*0.2\"},\n" + + " {\"action\":\"close\"}]"; + + private static String rectangleKey = "{\"ref\":\"rectangle\"}"; + private static String rectangleValue = "[{\"action\": \"move\",\"x\": \"0\",\"y\": \"0\"},\n" + + "{\"action\": \"line\",\"x\": \"w\",\"y\": \"0\"},\n" + + "{\"action\": \"line\",\"x\": \"w\",\"y\": \"h\"},\n" + + "{\"action\": \"line\",\"x\": \"0\",\"y\": \"h\"},\n" + + "{\"action\": \"close\"}]"; + + private static String parallelGatewaykey = "{\"ref\":\"parallel_gateway\"}"; + private static String parallelGatewayValue = "[{\"action\":\"move\", \"x\":\"w*0.5 - Math.min(w,h)*0.04\", \"y\":\"h*0.5 - h*0.5*0.5\"},\n" + + " {\"action\":\"line\", \"x\":\"w*0.5 - Math.min(w,h)*0.04\", \"y\":\"h*0.5 + h*0.5*0.5\"},\n" + + " {\"action\":\"line\", \"x\":\"w*0.5 + Math.min(w,h)*0.04\", \"y\":\"h*0.5 + h*0.5*0.5\"},\n" + + " {\"action\":\"line\", \"x\":\"w*0.5 + Math.min(w,h)*0.04\", \"y\":\"h*0.5 - h*0.5*0.5\"},\n" + + " {\"action\":\"line\", \"x\":\"w*0.5 - Math.min(w,h)*0.04\", \"y\":\"h*0.5 - h*0.5*0.5\"},\n" + + " {\"action\":\"close\"},\n" + + " {\"action\":\"move\", \"x\":\"w*0.5 - w*0.5*0.5\", \"y\":\"h*0.5 - Math.min(w,h)*0.04\"},\n" + + " {\"action\":\"line\", \"x\":\"w*0.5 - w*0.5*0.5\", \"y\":\"h*0.5 + Math.min(w,h)*0.04\"},\n" + + " {\"action\":\"line\", \"x\":\"w*0.5 + w*0.5*0.5\", \"y\":\"h*0.5 + Math.min(w,h)*0.04\"},\n" + + " {\"action\":\"line\", \"x\":\"w*0.5 + w*0.5*0.5\", \"y\":\"h*0.5 - Math.min(w,h)*0.04\"},\n" + + " {\"action\":\"line\", \"x\":\"w*0.5 - w*0.5*0.5\", \"y\":\"h*0.5 - Math.min(w,h)*0.04\"},\n" + + " {\"action\":\"close\"}]"; + + private static String gRoundKey = "{\"ref\":\"g_round\"}"; + private static String getRoundValue = "[{\"action\":\"move\", \"x\":\"w*0.5 - w*0.25\", \"y\":\"h*0.5\"},\n" + + " {\"action\":\"curve\", \"x1\":\"w*0.5 - w*0.25\", \"y1\":\"h*0.5 - h*2/3*0.5\", \"x2\":\"w*0.5 + w*0.25\", \"y2\":\"h*0.5 - h*2/3*0.5\", \"x\":\"w*0.5 + w*0.25\", \"y\":\"h*0.5\"},\n" + + " {\"action\":\"curve\", \"x1\":\"w*0.5 + w*0.25\", \"y1\":\"h*0.5 + h*2/3*0.5\", \"x2\":\"w*0.5 - w*0.25\", \"y2\":\"h*0.5 + h*2/3*0.5\", \"x\":\"w*0.5 - w*0.25\", \"y\":\"h*0.5\"},\n" + + " {\"action\":\"close\"}]"; + + // EPC与BPMN模型中的图形的映射关系 + public static Map shapeNameMapping = new HashMap<>(); + + // 存储schema中图形ref的引用 + public static Map schemaShapeMapping = new HashMap<>(); + + static { + shapeNameMapping.put("method_approval_node","userTask"); // 线上审批 -> 人工任务 + shapeNameMapping.put("method_service_node","manualTask"); // 线下审批 -> 手工任务 + shapeNameMapping.put("method_approval_node3","manualTask"); // 系统任务 -> 手工任务 + shapeNameMapping.put("method_service_node4","manualTask"); // 人工任务 -> 手工任务 + shapeNameMapping.put("procedure","textAnnotation"); // 流程接口 -> 注释 + shapeNameMapping.put("and","inclusiveGateway"); // 与 -> 包容网关 + shapeNameMapping.put("or","parallelGateway"); // 或 -> 并行网关 + shapeNameMapping.put("xor","exclusiveGateway"); // 异或 -> 排它网关 + + shapeNameMapping.put("event","messageIntermediateThrowingEvent"); // 事件 -> 抛出消息事件 + + schemaShapeMapping.put(gateWay0Key,gateWay0Value); + schemaShapeMapping.put(roundKey,roundValue); + schemaShapeMapping.put(roundRectangleKey,roundRectangleValue); + schemaShapeMapping.put(scriptTaskKey,scriptTaskValue); + schemaShapeMapping.put(manualTaskKey,manualTaskValue); + schemaShapeMapping.put(rectangleKey,rectangleValue); + schemaShapeMapping.put(parallelGatewaykey,parallelGatewayValue); + schemaShapeMapping.put(gRoundKey,getRoundValue); + } + /** * 匹配转换的类型 * @param sourceMethod @@ -82,4 +195,14 @@ public class ConvertUtil { } return result; } + + // 根据EPC的图形名称获取映射后的BPMN的图形名称 + public static String epcToBPMNShapeMapping(String shapeName){ + return shapeNameMapping.get(shapeName); + } + + public static Map getSchemaShapeMapping(){ + return schemaShapeMapping; + } + }