diff --git a/com.actionsoft.apps.coe.pal.batch/excel/模型导入模板.xlsx b/com.actionsoft.apps.coe.pal.batch/excel/模型导入模板.xlsx new file mode 100644 index 00000000..c6c96d2c Binary files /dev/null and b/com.actionsoft.apps.coe.pal.batch/excel/模型导入模板.xlsx differ diff --git a/com.actionsoft.apps.coe.pal.batch/lib/com.actionsoft.apps.coe.pal.batch.jar b/com.actionsoft.apps.coe.pal.batch/lib/com.actionsoft.apps.coe.pal.batch.jar index e85acaed..c0c97c1d 100644 Binary files a/com.actionsoft.apps.coe.pal.batch/lib/com.actionsoft.apps.coe.pal.batch.jar and b/com.actionsoft.apps.coe.pal.batch/lib/com.actionsoft.apps.coe.pal.batch.jar differ diff --git a/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/constant/BatchConst.java b/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/constant/BatchConst.java index 2ae6d629..b2dfd637 100644 --- a/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/constant/BatchConst.java +++ b/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/constant/BatchConst.java @@ -24,13 +24,15 @@ public class BatchConst { // 批量创建标识 public static final String PROCESS_LIST = "processList";// 流程清单 public static final String SHAPE_LIST = "shapeList";// 模型结构 - + public static final String SHAPE_IMPORT = "shapeImport";// 模型导入 + // 模版文件路径 public static final String TEMPLATE_FILE_PATH = AppsConst.APPS_ROOT + AppsConst.FOLDER_INSTALL + File.separator + APP_ID + File.separator + "excel" + File.separator; // 模版文件名称 public static final String PROCESS_LIST_TEMPLATE_FILE_SUFFIX = "清单模板.xlsx"; public static final String SHAPE_LIST_TEMPLATE_FILE_SUFFIX = "模型结构模板.xlsx"; - + public static final String SHAPE_IMPORT_TEMPLATE_FILE_SUFFIX = "模型导入模板.xlsx"; + // 日志结束语 public static final String END_LOG = "**建议拷贝本次输出日志做备忘"; diff --git a/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/BatchWeb.java b/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/BatchWeb.java index 05ec85b4..b7b33b00 100644 --- a/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/BatchWeb.java +++ b/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/BatchWeb.java @@ -2,13 +2,12 @@ package com.actionsoft.apps.coe.pal.batch.web; import com.actionsoft.apps.coe.pal.batch.constant.BatchConst; import com.actionsoft.apps.coe.pal.batch.util.LogUtil; +import com.actionsoft.apps.coe.pal.batch.util.POIUtil; import com.actionsoft.apps.coe.pal.batch.web.create.process.CreateProcessExcel; import com.actionsoft.apps.coe.pal.batch.web.create.process.ImportProcessExcel; import com.actionsoft.apps.coe.pal.batch.web.create.process.ProcessUtil; import com.actionsoft.apps.coe.pal.batch.web.create.process.ValidProcessExcel; -import com.actionsoft.apps.coe.pal.batch.web.create.shape.CreateShapeExcel; -import com.actionsoft.apps.coe.pal.batch.web.create.shape.ImportShapeExcel; -import com.actionsoft.apps.coe.pal.batch.web.create.shape.ValidShapeExcel; +import com.actionsoft.apps.coe.pal.batch.web.create.shape.*; import com.actionsoft.apps.coe.pal.batch.web.replace.FilterReplaceProcess; import com.actionsoft.apps.coe.pal.batch.web.replace.ReplaceProcessSave; import com.actionsoft.apps.coe.pal.constant.CoEConstant; @@ -39,6 +38,8 @@ import com.actionsoft.sdk.local.SDK; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.File; import java.io.IOException; @@ -102,7 +103,9 @@ public class BatchWeb extends ActionWeb { if (BatchConst.PROCESS_LIST.equals(type)) { ro = new CreateProcessExcel().createProcessTemplate(uc, wsId, methodCategory); } else if (BatchConst.SHAPE_LIST.equals(type)) { - ro = new CreateShapeExcel().createShapeTemplate(uc, wsId, methodCategory); + ro = new CreateShapeExcel().createShapeImportTemplate(uc, wsId, methodCategory); + } else if (BatchConst.SHAPE_IMPORT.equals(type)) { + ro = new CreateShapeExcel().createShapeImportTemplate(uc, wsId, methodCategory); } return ro.toString(); } @@ -328,12 +331,34 @@ public class BatchWeb extends ActionWeb { e.printStackTrace(); } logPath = simpleLogFile.getPath(); - + + DCPluginProfile dcProfile1 = DCProfileManager.getDCProfile(BatchConst.APP_ID, BatchConst.TMP); + DCContext dc1 = new DCContext(uc, dcProfile1, BatchConst.APP_ID, BatchConst.UPLOAD, object.getString("fileValue")); + String fileLength = dc1.getFileLength(); + File file = new File(dc1.getPath()); + XSSFSheet sheet = null; + if (!file.isFile()){ + File[] files = file.listFiles(); + File file1 = files[0]; + XSSFWorkbook wb = POIUtil.getWorkbook(file1); + if (wb != null){ + String sheetName1 = ShapeUtil.getModelShapeImportName(methodCategory); + sheet = wb.getSheet(sheetName1); + sheetName1.length(); + } + } + if ("processList".equals(type)) {// 流程清单保存 new Thread(()->{new ImportProcessExcel().execute(uc, object, simpleLogFile, fullLogFile, logId, methodCategory);}) .start(); } if ("shapeList".equals(type)) {// 模型结构保存 - new Thread(()->{new ImportShapeExcel().execute(uc, object, simpleLogFile, fullLogFile, logId, methodCategory);}) .start(); + if (sheet!=null){ + //模型导入保存 + new Thread(()->{new ImportShapeExcel1().execute(uc, object, simpleLogFile, fullLogFile, logId, methodCategory);}) .start(); +// new ImportShapeExcel1().execute(uc, object, simpleLogFile, fullLogFile, logId, methodCategory); + }else { + new Thread(()->{new ImportShapeExcel().execute(uc, object, simpleLogFile, fullLogFile, logId, methodCategory);}) .start(); + } } ResponseObject ro = ResponseObject.newOkResponse(); ro.put("type", type); diff --git a/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/process/ProcessUtil.java b/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/process/ProcessUtil.java index 9e79f548..8b0611eb 100644 --- a/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/process/ProcessUtil.java +++ b/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/process/ProcessUtil.java @@ -329,5 +329,33 @@ public class ProcessUtil { } return recentVerList; } - + + /** + * 获取指定根目录下所有的使用中版本模型列表 + * @param wsId + * @param category 根节点分类,如process,data,org等 + * @return + */ + public static List getInuseRepositoryList(String wsId, String category) { + List list = new ArrayList<>(); + Set ids = new HashSet<>(); + PALRepositoryCache.getAllChildrenModelsByPid(wsId, category, list, ids); + // 找到使用中,只匹配使用中(在日志中添加此明显提示 todo) + List recentVerList = new ArrayList<>(); + Map modelMap = new HashMap<>(); + for (PALRepositoryModel model : list) { + if (!modelMap.containsKey(model.getVersionId())) { + modelMap.put(model.getVersionId(), model); + } else { + if (!modelMap.get(model.getVersionId()).isUse() && model.isUse()) { + modelMap.put(model.getVersionId(), model); + } + } + } + for (Map.Entry entry : modelMap.entrySet()) { + recentVerList.add(entry.getValue()); + } + return recentVerList; + } + } diff --git a/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/CreateShapeExcel.java b/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/CreateShapeExcel.java index 5e845063..a5910b72 100644 --- a/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/CreateShapeExcel.java +++ b/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/CreateShapeExcel.java @@ -5,6 +5,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.*; +import java.util.stream.Collectors; import com.actionsoft.apps.coe.pal.batch.web.create.process.ProcessConst; import com.actionsoft.apps.coe.pal.batch.web.create.process.ProcessUtil; @@ -51,6 +52,33 @@ public class CreateShapeExcel { ro.put("url", createExcelTemplate(uc, methodCategory, methodNames, shapeNames)); return ro; } + public ResponseObject createShapeImportTemplate(UserContext uc, String wsId, String methodCategory) { + + //导入泳道图特殊处理 + if (!methodCategory.equals("process")){ + return ResponseObject.newErrResponse("仅支持流程制度下泳道图模型导入"); + } + // 获取当前资产库模型下的所有类别 + Map> shapeTitleMap = ShapeUtil.getProcessShapeTitles(methodCategory); + //泳道图特殊处理 + Map> tempMap = new HashMap<>(); + shapeTitleMap.entrySet().stream().filter(item->{ + return item.getKey().equals("process.flowchart"); + }).forEach(item->{ + tempMap.put(item.getKey(),item.getValue()); + }); + shapeTitleMap = tempMap; + + List methodNames = new ArrayList<>();// 建模方法分类 + List shapeNames = new ArrayList<>();// 形状类型名称 + for (Map.Entry> entry : shapeTitleMap.entrySet()) { + methodNames.add(I18nRes.findValue(CoEConstant.APP_ID, entry.getKey())); + shapeNames.addAll(entry.getValue()); + } + ResponseObject ro = ResponseObject.newOkResponse(); + ro.put("url", createExcelImportTemplate(uc, methodCategory, methodNames, shapeNames)); + return ro; + } /** * 获取sheet页名称 @@ -210,4 +238,133 @@ public class CreateShapeExcel { return downloadURL; } + private String createExcelImportTemplate(UserContext uc, String methodCategory, List methodNames, List shapeNames) { + // 模型名称、模型类型、形状名称、形状类型、扩展、... + String groupValue = "template"; + String fileValue = UUIDGener.getUUID(); + DCPluginProfile dcProfile = DCProfileManager.getDCProfile(BatchConst.APP_ID, BatchConst.TMP); + DCContext dcContext = new DCContext(uc, dcProfile, BatchConst.APP_ID, groupValue, fileValue); + UtilFile utilFile = new UtilFile(dcContext.getPath()); + // 创建文件 + utilFile.mkdirs(); + String excelName = I18nRes.findValue(CoEConstant.APP_ID, methodCategory) + BatchConst.SHAPE_IMPORT_TEMPLATE_FILE_SUFFIX; + File file = new File(utilFile + File.separator + excelName); + try { + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + try { + XSSFWorkbook wb = new XSSFWorkbook();// 创建Excel工作簿对象 + // 模型清单页签 + XSSFSheet sheet = wb.createSheet(ShapeUtil.getModelShapeImportName(methodCategory));// 创建工作表对象 + XSSFRow titleRow = sheet.createRow(0); + titleRow.setHeightInPoints(25); + // 单元格样式 + XSSFCellStyle cellStyle = POIUtil.getMainCellStyle(wb); + XSSFCellStyle cellStyle2 = POIUtil.getExtendCellStyle(wb); + XSSFCellStyle commStyle = POIUtil.getTableCellStyle(wb); + List titleList = new ArrayList<>(); + int index = 0; + // 模型名称 + titleList.add(titleRow.createCell((short)index)); + titleList.get((short)index).setCellStyle(cellStyle); + titleList.get((short)index).setCellValue(ShapeConst.TABLE_REPOSITORY_NAME); + sheet.setColumnWidth((short)index, 13000);// 设置当前列宽度 + index++; + // 模型类型 + titleList.add(titleRow.createCell((short)index)); + titleList.get((short)index).setCellStyle(cellStyle); + titleList.get((short)index).setCellValue(ShapeConst.TABLE_REPOSITORY_TYPE); + sheet.setColumnWidth((short)index, 6000);// 设置当前列宽度 + // 设置下拉框 + XSSFDataValidationHelper dvHelper = new XSSFDataValidationHelper(sheet); + XSSFDataValidationConstraint dvConstraint = (XSSFDataValidationConstraint) dvHelper.createExplicitListConstraint(methodNames.toArray(new String [methodNames.size()])); + CellRangeAddressList addressList = new CellRangeAddressList(1, 65536, 1, 1); + XSSFDataValidation validation =(XSSFDataValidation)dvHelper.createValidation(dvConstraint, addressList); + sheet.addValidationData(validation); + index++; + // 节点名称 + titleList.add(titleRow.createCell((short)index)); + titleList.get((short)index).setCellStyle(cellStyle); + titleList.get((short)index).setCellValue(ShapeConst.TABLE_SHAPE_NAME); + sheet.setColumnWidth((short)index, 13000);// 设置当前列宽度 + index++; + // 节点类型 + titleList.add(titleRow.createCell(index)); + titleList.get((short)index).setCellStyle(cellStyle); + titleList.get((short)index).setCellValue(ShapeConst.TABLE_SHAPE_TYPE); + sheet.setColumnWidth((short)index, 6000);// 设置当前列宽度 + // 设置下拉框 + // 下拉框数量超过20个,通过sheet页建立下拉框选择 +// XSSFDataValidationHelper dvHelper2 = new XSSFDataValidationHelper(sheet); +// XSSFDataValidationConstraint dvConstraint2 = (XSSFDataValidationConstraint) dvHelper2.createExplicitListConstraint(shapeNames.toArray(new String [shapeNames.size()])); +// CellRangeAddressList addressList2 = new CellRangeAddressList(1, 65536, 3, 3); +// XSSFDataValidation validation2 =(XSSFDataValidation)dvHelper2.createValidation(dvConstraint2, addressList2); +// sheet.addValidationData(validation2); + index++; + //节点分支 + titleList.add(titleRow.createCell((short)index)); + titleList.get((short)index).setCellStyle(cellStyle); + titleList.get((short)index).setCellValue(ShapeConst.TABLE_SHAPE_BRANCH); + sheet.setColumnWidth((short)index, 6000);// 设置当前列宽度 + index++; + //节点编号 + titleList.add(titleRow.createCell((short)index)); + titleList.get((short)index).setCellStyle(cellStyle); + titleList.get((short)index).setCellValue(ShapeConst.TABLE_SHAPE_NUM); + sheet.setColumnWidth((short)index, 6000);// 设置当前列宽度 + index++; + + // 以下为扩展 + titleList.add(titleRow.createCell(index)); + titleList.get((short)index).setCellStyle(cellStyle2); + titleList.get((short)index).setCellValue(ShapeConst.TABLE_EXTAND_EXAMPLE); + sheet.setColumnWidth((short)index, 6000);// 设置当前列宽度 + + index++; + + titleList.add(titleRow.createCell(index)); + titleList.get((short)index).setCellStyle(cellStyle2); + titleList.get((short)index).setCellValue(ShapeConst.TABLE_EXTAND_EXAMPLE2); + sheet.setColumnWidth((short)index, 4000);// 设置当前列宽度 + + // 创建20行的表格 + for (int i = 0; i < 20; i++) { + XSSFRow dataRow = sheet.createRow(i+1); + List dataList = new ArrayList<>(); + for (int j = 0; j < index + 1; j++) { + dataList.add(dataRow.createCell(j)); + dataList.get((short)j).setCellStyle(commStyle); + } + } + // 增加说明页 + File descFile = new File(BatchConst.TEMPLATE_FILE_PATH + BatchConst.SHAPE_IMPORT_TEMPLATE_FILE_SUFFIX); + if (descFile.exists()) { + XSSFWorkbook descWb; + try { + descWb = new XSSFWorkbook(descFile); + XSSFSheet descSheet = descWb.getSheetAt(1); + if (descSheet != null) { + XSSFSheet sheet2 = wb.createSheet(ProcessConst.SHEET_HELPER); + POIUtil.copySheet(wb, descSheet, sheet2, true); + } + } catch (InvalidFormatException e) { + e.printStackTrace(); + } + + } + // 处理形状类型下拉框 + POIUtil.setLongXSSFValidation(wb, shapeNames.toArray(new String [shapeNames.size()]), sheet, 1, 65536, 3, 2, "形状类型选项"); + wb.write(new FileOutputStream(file)); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + DCContext dc = new DCContext(uc, dcProfile, BatchConst.APP_ID, groupValue, fileValue, file.getName()); + String downloadURL = dc.getDownloadURL() + "&isInline=false"; + return downloadURL; + } + } diff --git a/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/ImportShapeExcel1.java b/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/ImportShapeExcel1.java new file mode 100644 index 00000000..575b5863 --- /dev/null +++ b/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/ImportShapeExcel1.java @@ -0,0 +1,1448 @@ +package com.actionsoft.apps.coe.pal.batch.web.create.shape; + +import com.actionsoft.apps.coe.pal.batch.constant.BatchConst; +import com.actionsoft.apps.coe.pal.batch.util.LogUtil; +import com.actionsoft.apps.coe.pal.batch.web.create.shape.model.CellObject; +import com.actionsoft.apps.coe.pal.constant.CoEConstant; +import com.actionsoft.apps.coe.pal.pal.repository.PALRepositoryAPIManager; +import com.actionsoft.apps.coe.pal.pal.repository.PALRepositoryQueryAPIManager; +import com.actionsoft.apps.coe.pal.pal.repository.cache.PALRepositoryCache; +import com.actionsoft.apps.coe.pal.pal.repository.designer.constant.CoeDesignerConstant; +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.relation.cache.DesignerShapeRelationCache; +import com.actionsoft.apps.coe.pal.pal.repository.designer.relation.dao.DesignerShapeRelationDao; +import com.actionsoft.apps.coe.pal.pal.repository.designer.relation.model.DesignerShapeRelationModel; +import com.actionsoft.apps.coe.pal.pal.repository.designer.util.CoeDesignerUtil; +import com.actionsoft.apps.coe.pal.pal.repository.model.PALRepositoryModel; +import com.actionsoft.apps.coe.pal.yili.log.datamigration.log.Cache.LogRealTimeCountCache; +import com.actionsoft.apps.coe.pal.yili.log.datamigration.log.Model.LogRealTimeCountModel; +import com.actionsoft.bpms.commons.security.logging.model.Level; +import com.actionsoft.bpms.org.model.DepartmentModel; +import com.actionsoft.bpms.org.model.RoleModel; +import com.actionsoft.bpms.org.model.UserModel; +import com.actionsoft.bpms.server.UserContext; +import com.actionsoft.bpms.util.UUIDGener; +import com.actionsoft.bpms.util.UtilDate; +import com.actionsoft.bpms.util.UtilString; +import com.actionsoft.i18n.I18nRes; +import com.actionsoft.sdk.local.SDK; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.google.common.util.concurrent.AtomicDouble; +import org.apache.commons.lang.StringUtils; +import org.codehaus.groovy.util.ListHashMap; +import org.mozilla.javascript.Context; +import org.mozilla.javascript.Scriptable; + +import java.io.File; +import java.io.IOException; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.text.SimpleDateFormat; +import java.util.*; + +/** + * 导入模型结构 + * @author sunlh + * + */ +public class ImportShapeExcel1 { + + private Map> processShapeDefinitionMap = new HashMap<>(); + private Map> methodAttrsMap = new HashMap<>(); + + private String linkerDef = "{\"name\":\"linker\",\"text\":\"\",\"group\":\"\",\"linkerType\":\"broken\",\"points\":[{\"x\":0,\"y\":0},{\"x\":0,\"y\":0}],\"locked\":false,\"dataAttributes\":[{\"name\":\"AWSProperties\",\"type\":\"string\",\"value\":\"\",\"category\":\"default\",\"id\":\"AWSPropertiesID\",\"shapeDesc\":\"\"}],\"orderIndex\":0,\"props\":{\"zindex\":0},\"lineStyle\":{\"lineWidth\":2,\"lineColor\":\"50,50,50\",\"lineStyle\":\"solid\",\"beginArrowStyle\":\"none\",\"endArrowStyle\":\"solidArrow\"},\"fontStyle\":{\"fontFamily\":\"Arial\",\"size\":12,\"color\":\"50,50,50\",\"bold\":false,\"italic\":false,\"underline\":false,\"textAlign\":\"center\"},\"from\":{\"x\":0,\"y\":0,\"angle\":3.141592653589793,\"id\":\"\"},\"to\":{\"id\":\"\",\"x\":0,\"y\":0,\"angle\":0}}"; + private long startTime; + private long endTime; + private File simpleLogFile; + private File fullLogFile; + private File checkTableFile;// 记录校验的表格结果 + private String logId; + private String wsId; + private String teamId; + private UserContext uc; + + public void execute(UserContext uc, JSONObject object, File simpleLogFile, File fullLogFile, String logId, String methodCategory) { + this.fullLogFile = fullLogFile; + this.simpleLogFile = simpleLogFile; + // 单独创建一个成功日志 +// successLogFile = new File(fullLogFile.getParentFile().getPath() + File.separator + BatchConst.IMPORT_LOG_FILE_SUCCESS); +// matchErrImportFile = new File(fullLogFile.getParentFile().getPath() + File.separator + BatchConst.IMPORT_LOG_FILE_MATCH_ERR); + checkTableFile = new File(fullLogFile.getParentFile().getPath() + File.separator + BatchConst.IMPORT_LOG_FILE_CHECK_TABLE); + try { +// successLogFile.createNewFile(); +// matchErrImportFile.createNewFile(); + checkTableFile.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + this.logId = logId; + this.startTime = System.currentTimeMillis(); + this.wsId = object.getString("wsId"); + this.teamId = object.getString("teamId"); + this.uc = uc; + Timestamp startDate = new Timestamp(startTime); + LogUtil.appendLog("注:该日志文件存储简要日志信息", simpleLogFile); + LogUtil.appendLog("注:该日志文件存储详细日志信息", fullLogFile); + + LogUtil.appendLog("\n[信息]操作人:" + uc.getUserName() + "<" + uc.getUID() + ">", simpleLogFile, fullLogFile); + LogUtil.appendLog("[信息]操作时间:" + UtilDate.datetimeFormat(startDate), simpleLogFile, fullLogFile); + // todo +// LogUtil.appendLog("[信息]模型文件:" + fileName, simpleLogFile, fullLogFile); +// LogUtil.appendLog("[信息]模型文件路径:" + filePath, simpleLogFile, fullLogFile); + + LogUtil.appendLog("PAL 泳道图Excel批量导入模型 Begin " + UtilDate.datetimeFormat(startDate), simpleLogFile, fullLogFile); + LogUtil.appendLog("--------------------------------", simpleLogFile, fullLogFile); + LogUtil.appendLog("若模型存在多版本,只与模型使用中版本进行匹配,过往版本忽略不进行任何处理,若最新版本模型非可编辑状态(已发布、已停用、审批中),直接跳过该模型,不做任何调整", simpleLogFile, fullLogFile); + + + + JSONObject data = object.getJSONObject("data"); + JSONArray importData = data.getJSONArray("okData"); + + + //文件下根据分支分组表格数据 + Map>> fileData = new LinkedHashMap<>(); + this.collectTableCellBranch(importData,fileData); + + //<文件id,文件下的分支数据>,计算基准数据map + Map>>>> fileDataMap = new LinkedHashMap<>(); + //文件下特殊分支处理, 只绘制图形不连线 + Map> specialMap = new LinkedHashMap<>(); + + this.transformCollectBranchToCellMap(fileData,fileDataMap,specialMap); + + + + //根据基准数据绘制图形+连线关系 + for (String repositoryId : fileDataMap.keySet()) { + double offsetX = ShapeConst.SHAPE_BRANCH_INTERVAL; + double rightMaxLine = 0; + + LogUtil.appendLog("准备导入" + I18nRes.findValue(CoEConstant.APP_ID, methodCategory) + "数据[开始]", fullLogFile); + + + //计算后形状与连线保存,这里顺序 + Map> nodeMap = new LinkedHashMap<>(); + + // 形状关联属性结果集 + List relationList = new ArrayList<>(); + + //常规图形绘制 + LogUtil.appendLog(BatchConst.LOG_DESC + "[执行阶段][绘制常规分支图形]", simpleLogFile, fullLogFile); + Map>>> branchData = fileDataMap.get(repositoryId); + double maxRight = this.drawBranchShape(repositoryId, branchData, offsetX, nodeMap, relationList); + rightMaxLine = Math.max(rightMaxLine,maxRight); + + offsetX = rightMaxLine + 150; + rightMaxLine = offsetX; + + //特殊图形绘制 + LogUtil.appendLog(BatchConst.LOG_DESC + "[执行阶段][绘制特殊分支图形]", simpleLogFile, fullLogFile); + List specicalCell = specialMap.get(repositoryId); + if (specicalCell == null || specicalCell.isEmpty()){ + continue; + } + for (int i = 0; i < specicalCell.size(); i++) { + CellObject node = specicalCell.get(i); + + //节点的图形数据, + List shapes = new ArrayList<>(); + + //节点画图, + JSONObject shape = this.drawShape(node, 0, offsetX, i, i); + shapes.add(shape); + + nodeMap.put(this.getCellObjectUUID(node),shapes); + } + + //文件操作 + LogUtil.appendLog(BatchConst.LOG_END + "[执行阶段][保存模型阶段]", simpleLogFile, fullLogFile); + this.saveDefine(repositoryId,nodeMap); + + } + LogUtil.appendLog(BatchConst.LOG_END + "[执行结束][Excel导入完成]", simpleLogFile, fullLogFile); + } + + private double drawBranchShape(String repositoryId,Map>>> branchData,double originOffsetX,Map> nodeMap,List relationList){ + if (branchData==null || branchData.isEmpty()){ + return 0; + } + + double rightMaxLine = 0; + double offsetX = originOffsetX; + + for (Map.Entry>>> branch : branchData.entrySet()) { + //int offsetX = offsetX + rightMaxLine; + // <层级,同级别map> + Map>> levelMap = branch.getValue(); + + //获取最大层级 + int maxLevel = levelMap.keySet().size(); + + //遍历层级,产出图+连线 + for (int level = 0; level < maxLevel; level++) { + //同层级多分支节点信息, <序号,同序号listNode> + Map> numList = levelMap.get("" + level); + + + //计算同层级索引 + int levelNodeIndex = 0; + for (int i = 0; i < numList.keySet().size()+1; i++) { +// double offset = startNodeOffset; + //构建同层级的分支序号 + String levelNo = this.getLevelNo(level, i); + + //当前分支的最终节点,同序号节点list + List nodes = numList.get(levelNo); + if (null == nodes){ + continue; + } + +// if (levelNo.equals("5.2")){ +// Object o = new Object(); +// } + + + //找到上级节点,可跨级 + JSONObject upNodes = this.findUpLevelNode(levelNo, levelMap, nodeMap); + JSONArray upList = upNodes.getJSONArray("upList"); + //根据上级计算offset,没有上级,一个上级,多个上级 + double levelOffset = offsetX; + int size = 1; + if (null !=upList && !upList.isEmpty()){ + if (upList.size()==1){ + //只有一个上级节点 + JSONObject upNode = upList.getJSONObject(0); + levelOffset = upNode.getJSONObject("props").getDouble("x"); + if (upNode.getString("shapeNum").contains(".")){ + //分支下的分支计算偏移量重新计算 + levelNodeIndex = 0; + size = nodes.size(); + }else { + size = numList.keySet().size(); + } + }else{ + //多个父级节点计算偏移量 + Double minX = null; + Double maxX = null; + for (int upIndex = 0; upIndex < upList.size(); upIndex++) { + JSONObject upNode = upList.getJSONObject(upIndex); + JSONObject props = (JSONObject)upNode.get("props"); + if (minX == null && maxX == null){ + minX = props.getDouble("x"); + maxX = minX; + } + maxX = Math.max(props.getDouble("x"), maxX); + minX = Math.min(props.getDouble("x"), minX); + } + levelOffset =((maxX - minX) * 0.5 ) + minX; + } + } + + //同级别节点是,一分,二分节点节点计算offset + double offset = this.getLevelStartNodeOffset(size,levelOffset); + + + for (int nodeIndex = 0; nodeIndex < nodes.size(); nodeIndex++,levelNodeIndex++) { + CellObject node = nodes.get(nodeIndex); + + //保存当前节点的图形数据+连线数据, + List shapes = new ArrayList<>(); + + //绘制当前节点图形 + JSONObject shape = this.drawShape(node, levelNodeIndex, offset, level, i); + + //计算最右边边界 + rightMaxLine = this.getrightMaxLine(shape, rightMaxLine); + + + //图形拓展属性处理 + JSONArray attributesJsonArray = new JSONArray(); + JSONArray expandArr = node.getExpandArr(); + this.handleExpandAttr(repositoryId,shape,expandArr,attributesJsonArray,relationList); + if (attributesJsonArray.size() > 0) { + JSONArray dataAttributes = shape.getJSONArray("dataAttributes"); + if (!dataAttributes.isEmpty() && dataAttributes.size() > 0) { + for (Object attribute : dataAttributes) { + JSONObject obj = (JSONObject) attribute; + if (obj.containsKey("attributesJsonArray")) { + obj.put("attributesJsonArray", attributesJsonArray); + break; + } + } + } + } + shapes.add(shape); + + if (upNodes.getBooleanValue("isUp")){ + //存在父级节点,计算与上级节点list的连线 + if (nodes.size()>1 && upList.size()>1){ + //多下级与多上级的连线不处理 + continue; + } + //与多个上级节点直接连线 + for (Object o : upList) { + JSONObject linker = this.drawLinker((JSONObject) o, shape, nodeIndex); + shapes.add(linker); + } + } + + //计算最终确定位置map的key:名称+类型+序号 + nodeMap.put(this.getCellObjectUUID(node),shapes); + } + } + } + offsetX = rightMaxLine + ShapeConst.SHAPE_BRANCH_INTERVAL; + } + + return rightMaxLine; + } + + private double getrightMaxLine(JSONObject shape,double rightMaxLine){ + if (null == shape){ + return 0; + } + + JSONObject props = shape.getJSONObject("props"); + Double x = props.getDouble("x"); + double shapeRight = x + ShapeConst.SHAPE_NODE_WIDTH; + return Math.max(shapeRight,rightMaxLine); + } + + private void handleExpandAttr(String repositoryId,JSONObject shape,JSONArray expandArr,JSONArray attributesJsonArray,List relationList){ + String shapeTitle = shape.getString("title"); + String shapeId = shape.getString("id"); + String shapeText = shape.getString("text"); + JSONObject methodAttr = ShapeUtil.getProcessShapeMethodAttr(wsId, "process.flowchart", shapeTitle); + + for (int i1 = 0; i1 < expandArr.size(); i1++) { + JSONObject cellData = expandArr.getJSONObject(i1); + + JSONObject attr = methodAttr.getJSONObject(cellData.getString("name")); + if (null == attr){ + return; + } + String ref = attr.getString("ref"); + boolean readonly = attr.getBooleanValue("readonly"); + String scope = attr.getString("scope"); + String attrName = attr.getString("title"); + String attrId = attr.getString("id"); + String type = attr.getString("type"); + String groupPath = attr.getString("groupPath"); + String attrKey = attr.getString("key"); + String attrValue = ""; + JSONObject object2 = new JSONObject(); + object2.put("ref", ref); + object2.put("readonly", readonly); + object2.put("scope", scope); + object2.put("name", attrName); + object2.put("id", attrId); + object2.put("type", type); + object2.put("groupPath", groupPath); + object2.put("key", attrKey); + object2.put("value", ""); + if ("string".equals(type) || "textarea".equals(type)) { + attrValue = cellData.getString("value"); + if (UtilString.isEmpty(attrValue)) { + attrValue = ""; + } + object2.put("value", attrValue); + attributesJsonArray.add(object2); + } else if ("relation".equals(type)) { + JSONObject refObj = JSONObject.parseObject(ref); + String relationType = refObj.getString("type");// 关联范围 file shape + JSONArray relations = cellData.getJSONObject("attr").getJSONArray("relations"); + if ("file".equals(relationType)) {// 关联模型文件 + JSONArray versionIds = new JSONArray(); + for (Object relation : relations) { + JSONObject obj = JSONObject.parseObject(relation.toString()); + DesignerShapeRelationModel model = new DesignerShapeRelationModel(); + model.setFileId(repositoryId); + model.setAttrId(attrId); + model.setId(UUIDGener.getUUID()); + model.setShapeId(shapeId); + model.setShapeText(shapeText); + model.setRelationFileId(obj.getString("versionId")); + model.setRelationShapeId(""); + model.setRelationShapeText(obj.getString("name")); + relationList.add(model); + versionIds.add(obj.getString("versionId")); + } + if (versionIds.size() > 0) { + object2.put("value", versionIds); + } + attributesJsonArray.add(object2); + } else {// 关联形状属性 + JSONArray shapeIds = new JSONArray(); + for (Object relation : relations) { + JSONObject obj = JSONObject.parseObject(relation.toString()); + DesignerShapeRelationModel model = new DesignerShapeRelationModel(); + model.setFileId(repositoryId); + model.setAttrId(attrId); + model.setId(UUIDGener.getUUID()); + model.setShapeId(shapeId); + model.setShapeText(shapeText); + model.setRelationFileId(obj.getString("fileId")); + model.setRelationShapeId(obj.getString("shapeId")); + model.setRelationShapeText(obj.getString("shapeText")); + relationList.add(model); + shapeIds.add(obj.getString("shapeId")); + } + if (shapeIds.size() > 0) { + object2.put("value", shapeIds); + } + attributesJsonArray.add(object2); + } + } else if ("awsorg".equals(type)) {// 关联aws的组织架构 + JSONObject object3 = cellData.getJSONObject("data"); + JSONArray deptArr = object3.getJSONArray("department");// 部门 + JSONArray roleArr = object3.getJSONArray("role");// 角色 + JSONArray positionArr = object3.getJSONArray("position");// 岗位 + JSONArray userArr = object3.getJSONArray("user");// 人员 + // 部门 + for (int l = 0; l < deptArr.size(); l++) { + String deptId = deptArr.getString(l); + DepartmentModel deptModel = SDK.getORGAPI().getDepartmentById(deptId); + if (deptModel == null) { + continue; + } + JSONObject deptObj = new JSONObject(); + deptObj.put("name", deptModel.getName()); + deptObj.put("id", deptId); + deptObj.put("type", "department"); + DesignerShapeRelationModel model = new DesignerShapeRelationModel(); + model.setFileId(repositoryId); + model.setAttrId(attrId); + model.setId(UUIDGener.getUUID()); + model.setShapeId(shapeId); + model.setShapeText(shapeText); + model.setRelationFileId("00000000-0000-0000-0000-000000000000"); + model.setRelationShapeId("00000000-0000-0000-0000-000000000000"); + model.setRelationShapeText(deptObj.toString()); + relationList.add(model); + } + // 角色 + for (int l = 0; l < roleArr.size(); l++) { + String roleId = roleArr.getString(l); + RoleModel roleModel = SDK.getORGAPI().getRoleById(roleId); + if (roleModel == null) { + continue; + } + JSONObject roleObj = new JSONObject(); + roleObj.put("name", roleModel.getName()); + roleObj.put("id", roleId); + roleObj.put("type", "role"); + DesignerShapeRelationModel model = new DesignerShapeRelationModel(); + model.setFileId(repositoryId); + model.setAttrId(attrId); + model.setId(UUIDGener.getUUID()); + model.setShapeId(shapeId); + model.setShapeText(shapeText); + model.setRelationFileId("00000000-0000-0000-0000-000000000000"); + model.setRelationShapeId("00000000-0000-0000-0000-000000000000"); + model.setRelationShapeText(roleObj.toString()); + relationList.add(model); + } + // 岗位 + for (int l = 0; l < positionArr.size(); l++) { + String positionId = positionArr.getString(l); + RoleModel positionModel = SDK.getORGAPI().getRoleById(positionId); + if (positionModel == null) { + continue; + } + JSONObject positionObj = new JSONObject(); + positionObj.put("name", positionModel.getName()); + positionObj.put("id", positionId); + positionObj.put("type", "position"); + DesignerShapeRelationModel model = new DesignerShapeRelationModel(); + model.setFileId(repositoryId); + model.setAttrId(attrId); + model.setId(UUIDGener.getUUID()); + model.setShapeId(shapeId); + model.setShapeText(shapeText); + model.setRelationFileId("00000000-0000-0000-0000-000000000000"); + model.setRelationShapeId("00000000-0000-0000-0000-000000000000"); + model.setRelationShapeText(positionObj.toString()); + relationList.add(model); + } + // 成员 + for (int l = 0; l < userArr.size(); l++) { + String userId = userArr.getString(l); + UserModel userModel = SDK.getORGAPI().getUser(userId); + if (userModel == null) { + continue; + } + JSONObject roleObj = new JSONObject(); + roleObj.put("name", userModel.getUserName()); + roleObj.put("id", userId); + roleObj.put("type", "user"); + DesignerShapeRelationModel model = new DesignerShapeRelationModel(); + model.setFileId(repositoryId); + model.setAttrId(attrId); + model.setId(UUIDGener.getUUID()); + model.setShapeId(shapeId); + model.setShapeText(shapeText); + model.setRelationFileId("00000000-0000-0000-0000-000000000000"); + model.setRelationShapeId("00000000-0000-0000-0000-000000000000"); + model.setRelationShapeText(roleObj.toString()); + relationList.add(model); + } + attributesJsonArray.add(object2); + } else if ("table".equals(type)) {// 表格类型 + object2.put("value", cellData.getJSONObject("tableValue")); + attributesJsonArray.add(object2); + } else {// 剩余的当作string处理 + attrValue = cellData.getString("value"); + if (UtilString.isEmpty(attrValue)) { + attrValue = ""; + } + object2.put("value", attrValue); + attributesJsonArray.add(object2); + } + } + } + + + private void saveDefine(String repositoryId,Map> nodeMap){ + PALRepositoryModel palModel = PALRepositoryCache.getCache().get(repositoryId); + BaseModel defineModel = CoeDesignerAPIManager.getInstance().getDefinition(palModel.getId(), 0); + if (defineModel == null) { + defineModel = CoeDesignerUtil.createModel(palModel.getId(), 0); + defineModel.setCreateHistory(false); + } + defineModel.setUpdateTime(new SimpleDateFormat(CoeDesignerConstant.DATE_TIME_STYLE_YYYY_MM_DD_HH_MM_SS).format(new Date())); + String define = defineModel.getDefinition(); + JSONObject definition = JSON.parseObject(define); + + JSONObject element = new JSONObject(); + for (List nodeValue : nodeMap.values()) { + for (JSONObject node : nodeValue) { + element.put(node.getString("id"),node); + } + } + definition.put("elements",element); + defineModel.setDefinition(definition.toString()); + // 保存文件 + CoeDesignerAPIManager.getInstance().storeDefinition(defineModel);// dao操作 + } + + private String getCellObjectUUID(CellObject node){ + //名称+类型+序号 + return node.getShapeName()+"|"+node.getShapeType()+"|"+node.getShapeBranch()+"|"+node.getShapeNum(); + } + + private JSONObject drawShape(CellObject node,int levelNodeIndex,double offset,int level,int zIndex){ + JSONObject shape = ShapeUtil.getProcessShapeDefinition("process.flowchart", node.getShapeType()); + // + shape.put("text", node.getShapeName()); + shape.put("id", UUIDGener.getUUID()); + shape.put("shapeNum", node.getShapeNum()); + + //计算位置 + double x = this.drawShapeX(levelNodeIndex, offset); + double y = this.drawShapeY(level); + JSONObject props = shape.getJSONObject("props"); + props.put("x", x); + props.put("y", y); + props.put("w", ShapeConst.SHAPE_NODE_WIDTH); + props.put("h", ShapeConst.SHAPE_NODE_HEIGHT); + props.put("zindex", zIndex+1); + shape.put("props", props); + + return shape; + } + + private JSONObject drawLinker(JSONObject fromNode,JSONObject toNode,int zIndex){ + JSONObject linker = JSONObject.parseObject(linkerDef); + linker.put("id", UUIDGener.getUUID()); + +// JSONObject fromNode = (JSONObject) node; +// JSONObject toNode = shape; + + JSONObject from = this.getShapeBottomPoint(fromNode); + from.put("id", fromNode.getString("id")); + from.put("angle",4.71238898038469 ); + + JSONObject to = this.getShapTopPoint(toNode); + to.put("id", toNode.getString("id")); + to.put("angle",1.5707963267948968 ); + + //设置linker的point + JSONArray points = new JSONArray(); + JSONObject point1 = new JSONObject(); + point1.put("x",from.getIntValue("x")); + point1.put("y",from.getIntValue("y")+((to.getIntValue("y")-from.getIntValue("y"))/2)); + points.add(point1); + JSONObject point2 = new JSONObject(); + point2.put("x", to.getIntValue("x")); + point2.put("y", from.getIntValue("y")+((to.getIntValue("y")-from.getIntValue("y"))/2)); + points.add(point2); + linker.put("points", points); + + //设置linker 点位 + JSONObject linkProps = new JSONObject(); + linkProps.put("zindex", zIndex+1); + linker.put("props", linkProps); + linker.put("from", from); + linker.put("to", to); + + return linker; + } + + /** + * 将入参table数据转化为文件--分支--具体数据格式的map存储, + * fileData存储结果内容 + * @param importData + * @param fileData + */ + private void collectTableCellBranch(JSONArray importData,Map>> fileData){ + for (int i = 0; i < importData.size(); i++) { + JSONObject rowData = importData.getJSONObject(i); + String repositoryId = rowData.getString("repositoryId"); + Map> branchMap = fileData.get(repositoryId); + if (branchMap == null){ + branchMap = new LinkedHashMap<>(); + } + + + String branch = ""; + + //解析入参的table数据 + JSONArray row = rowData.getJSONArray("row"); + CellObject cellObject = new CellObject(); + for (int rowIndex = 0; rowIndex < row.size(); rowIndex++) { + JSONObject cell = row.getJSONObject(rowIndex); + + JSONArray expandArr = new JSONArray(); + + if (cell.getString("name").equals(ShapeConst.TABLE_SHAPE_BRANCH)){ + //形状分支 + branch = cell.getString("value"); + cellObject.setShapeBranch(branch); + }else if (cell.getString("name").equals(ShapeConst.TABLE_REPOSITORY_NAME)){ + //模型名称 + cellObject.setModelName(cell.getString("value")); + }else if (cell.getString("name").equals(ShapeConst.TABLE_REPOSITORY_TYPE)){ + //模型类型 + cellObject.setModelType(cell.getString("value")); + }else if (cell.getString("name").equals(ShapeConst.TABLE_SHAPE_NAME)){ + //形状名称 + cellObject.setShapeName(cell.getString("value")); + }else if (cell.getString("name").equals(ShapeConst.TABLE_SHAPE_TYPE)){ + //形状类型 + cellObject.setShapeType(cell.getString("value")); + }else if (cell.getString("name").equals(ShapeConst.TABLE_SHAPE_BRANCH)){ + //形状分支 + cellObject.setShapeBranch(cell.getString("value")); + }else if (cell.getString("name").equals(ShapeConst.TABLE_SHAPE_NUM)){ + //形状序号 + cellObject.setShapeNum(cell.getString("value")); + }else { + //拓展属性 + expandArr.add(cell); + cellObject.setExpandArr(expandArr); + } + } + + //未获取到分支字段 + if (StringUtils.isEmpty(branch)){ + continue; + } + + //设置分支数据 + List cellObjects = branchMap.get(branch); + if (null == cellObjects){ + cellObjects = new ArrayList<>(); + } + cellObjects.add(cellObject); + branchMap.put(branch,cellObjects); + + //设置文件数据下分支map + fileData.put(repositoryId,branchMap); + } + } + + /** + * 将处理后的table数据转化为画图计算的cell 数据 + * 处理结果分为两种数据,一种统一计算map,一个是特殊处理的map + * @param fileData + * @param fileDataMap 统一计算map + * @param specialMap 特殊处理的map + */ + private void transformCollectBranchToCellMap(Map>> fileData,Map>>>> fileDataMap,Map> specialMap){ + for (String repositoryId : fileData.keySet()) { + //文件下分支数据 + Map>>> branchMap = fileDataMap.get(repositoryId); + if (null == branchMap){ + branchMap = new LinkedHashMap(); + } + + //整理后table数据中的分支数据 + Map> cellBranchMap = fileData.get(repositoryId); + for (String branch : cellBranchMap.keySet()) { + //branchMap 下的序号map + Map>> levelMap = branchMap.get(branch); + if (null == levelMap){ + levelMap = new LinkedHashMap<>(); + } + + //解析后table的分支下cell数据 + List cellList = cellBranchMap.get(branch); + for (CellObject cellObject : cellList) { + + String shapeNum = cellObject.getShapeNum(); + if (shapeNum.matches("[\\u4e00-\\u9fbb]+")){ + //序号中有中文,进入特殊处理分支 + //文件下特殊分支cell + List cellObjectList = specialMap.get(repositoryId); + if (null == cellObjectList){ + cellObjectList = new ArrayList<>(); + } + cellObjectList.add(cellObject); + specialMap.put(repositoryId,cellObjectList); + }else{ + //流程结束节点特殊处理 + if (cellObject.getShapeName().contains("流程结束")){ +// shapeNum = "-2"; + shapeNum = levelMap.keySet().size()+""; + cellObject.setShapeNum(shapeNum); + } + String shapeLevel = this.getCellObjecyLevel(shapeNum); + + //序号map下的层级map + Map> numMap = levelMap.get(shapeLevel); + if (null == numMap){ + numMap = new LinkedHashMap<>(); + } + //同一层级处理:层级map下的序号数组数据 + List cells = numMap.get(shapeNum); + if (null == cells){ + cells = new ArrayList<>(); + } + cells.add(cellObject); + //设置序号数据 + numMap.put(shapeNum,cells); + + levelMap.put(shapeLevel,numMap); + } + } + branchMap.put(branch,levelMap); + } + + fileDataMap.put(repositoryId,branchMap); + } + } + + private String getCellObjecyLevel(String shapeNum){ + if (shapeNum.contains(".")){ + //小数 + String[] split = shapeNum.split("\\."); + return split[0]; + } + return shapeNum; + } + + private String getLevelNo(int level,int index){ + if (index < 1){ + return ""+level; + } + return ""+level+"."+index; + } + + /** + * 找到已经画好的上级节点 改为递归 + * @param no + * @param levelMap + * @param nodeMap + * @return + */ + private JSONObject findUpLevelNode(String no,Map>> levelMap,Map> nodeMap){ + + JSONObject res =new JSONObject(); + res.put("isUp",false); + res.put("upList",null); + + List upList = this.find(no,levelMap,nodeMap); + if (upList.isEmpty()){ + return res; + } + + res.put("isUp",true); + res.put("upList",upList); + return res; + } + + + private List find(String no,Map>> levelMap,Map> nodeMap){ + List upList = new ArrayList<>(); + String level = ""; + String branch = ""; + if (no.contains(".")){ + //小数 + String[] split = no.split("\\."); + level = ""+ (Integer.parseInt(split[0])-1); + branch = split[1]; + }else { + //整数 + level = Integer.parseInt(no)-1 + ""; + } + if (level.equals("-1")){ + return upList; + } + + + Map> numMap = levelMap.get(level); + if (StringUtils.isEmpty(branch)){ + //整数节点找父级节点 + boolean flag = false; + for (String s : numMap.keySet()) { + + List nodes = numMap.get(s); + for (CellObject node : nodes) { + //计算最终确定位置map的key:名称+类型+序号 + String key = this.getCellObjectUUID(node); + List shapes = nodeMap.get(key); + if (null != shapes){ + for (JSONObject shape : shapes) { + if (!shape.get("name").equals("linker")){ + upList.add(shape); + } + } + } + } + if (s.contains(".")){ + //父级节点是分支下节点 + flag = true; + }else { + flag = false; + } + } + if (flag){ + //递归寻找多分支中整数节点的上级节点 + List list = this.find(level, levelMap, nodeMap); + + //获取当前上级节点的list中的分支情况 + List upBranchNo = this.getUpBranchNo(upList); + if (!upBranchNo.isEmpty()){ + for (JSONObject object : list) { + String shapeNum = object.getString("shapeNum"); + if (shapeNum.contains(".")){ + String branchNo = this.getBranchNo(shapeNum); + if (!upBranchNo.contains(branchNo)){ + upList.add(object); + } + } + } + } + } + }else { + //分支节点找父级节点 + List nodes = numMap.get(level +"."+ branch); + List nodes1 = numMap.get(level); + if ((nodes == null || nodes.isEmpty()) && (nodes1 == null || nodes1.isEmpty())){ + List list = this.find(level +"."+ branch, levelMap, nodeMap); + upList.addAll(list); + }else { + if (nodes!=null){ + for (CellObject node : nodes) { + //计算最终确定位置map的key:名称+类型+序号 + String key = this.getCellObjectUUID(node); + List shapes = nodeMap.get(key); + if (null != shapes){ + for (JSONObject shape : shapes) { + if (!shape.get("name").equals("linker")){ + upList.add(shape); + } + } + } + } + } + if (nodes1 != null){ + for (CellObject node : nodes1) { + //计算最终确定位置map的key:名称+类型+序号 + String key = this.getCellObjectUUID(node); + List shapes = nodeMap.get(key); + if (null != shapes){ + for (JSONObject shape : shapes) { + if (!shape.get("name").equals("linker")){ + upList.add(shape); + } + } + } + } + } + + + } + } + return upList; + } + + private List getUpBranchNo(List upList){ + List list = new ArrayList<>(); + for (JSONObject jsonObject : upList) { + String shapeNum = jsonObject.getString("shapeNum"); + if (shapeNum.contains(".")){ + //有分支 + String branchNo = this.getBranchNo(shapeNum); + if (StringUtils.isNotEmpty(branchNo) && !list.contains(branchNo)){ + list.add(branchNo); + } + } + } + + return list; + } + + private String getBranchNo (String no){ + String branch = ""; + if (no.contains(".")){ + //小数 + String[] split = no.split("\\."); + branch = split[1]; + } + + return branch; + } + + + /** + * 计算同级别节点初始偏移量 + * @param size + * @param originOffset + * @param width + * @param interval + * @return + */ + private double getLevelStartNodeOffset(int size ,double originOffset){ + if (size<=1){ + return originOffset; + } + + int width = ShapeConst.SHAPE_NODE_WIDTH; + + int interval = ShapeConst.SHAPE_NODE_INTERVAL; + + double offset = originOffset + 0.5*width; + double r = ((size-1)*0.5 * interval); + double q = size * 0.5; + double w = width * q; + double res = offset - r - w; + return res; + } + private double drawShapeX (int index,double offset){ + double x = index * (ShapeConst.SHAPE_NODE_WIDTH + ShapeConst.SHAPE_NODE_INTERVAL) + offset; + return x; + } + private double drawShapeY (int level){ + double y = level * (ShapeConst.SHAPE_HEIGHT_INTERVAL + ShapeConst.SHAPE_NODE_HEIGHT) + ShapeConst.SHAPE_HEIGHT_INTERVAL; + return y; + } + + private JSONObject getShapeBottomPoint(JSONObject shape){ + JSONObject point = new JSONObject(); + + JSONObject props = shape.getJSONObject("props"); + int shapex = props.getInteger("x"); + int shapey = props.getInteger("y"); + int shapew = props.getInteger("w"); + int shapeh = props.getInteger("h"); + + point.put("x",shapex+ 0.5*shapew ); + point.put("y",shapey+shapeh); + + return point; + } + private JSONObject getShapTopPoint(JSONObject shape){ + JSONObject point = new JSONObject(); + + JSONObject props = shape.getJSONObject("props"); + int shapex = props.getInteger("x"); + int shapey = props.getInteger("y"); + int shapew = props.getInteger("w"); + int shapeh = props.getInteger("h"); + + point.put("x",shapex+ 0.5*shapew ); + point.put("y",shapey); + + return point; + } + + + + + + + + + + + + + + /** + * 获取已有形状的最大纵向高度 + * @param elements + * @return + */ + private int getMaxPositionY(JSONObject elements) { + int max = 0; + Iterator it = elements.keySet().iterator(); + while (it.hasNext()) { + String key = it.next(); + JSONObject shape = elements.getJSONObject(key); + String shapeName = shape.getString("name"); + if(!"linker".equals(shapeName)) { + JSONObject props = shape.getJSONObject("props"); + int y = props.getIntValue("y") + props.getIntValue("h"); + max = max > y ? max : y; + } + } + return max; + } + + /** + * 获取形状的最大层级zindex + * @param elements + * @return + */ + private int getMaxPropsZIndex(JSONObject elements) { + int max = 0; + Iterator it = elements.keySet().iterator(); + while (it.hasNext()) { + String key = it.next(); + JSONObject shape = elements.getJSONObject(key); + JSONObject props = shape.getJSONObject("props"); + int zindex = props.getIntValue("zindex"); + max = max > zindex ? max : zindex; + } + return max; + } + + /** + * 数据更新/新增处理 + * @param palModel + * @param palId + * @param elements + * @param relationDao + * @param relationModelList + * @param delRelationIdList + */ + private void batchOpData(PALRepositoryModel palModel, String palId, JSONObject elements, DesignerShapeRelationDao relationDao, List relationModelList, List delRelationIdList) { + handleShapeDefaultAttr(wsId, palModel, elements, methodAttrsMap); + BaseModel defineModel = CoeDesignerAPIManager.getInstance().getDefinition(palId, 0); + if (defineModel == null) { + defineModel = CoeDesignerUtil.createModel(palId, 0); + defineModel.setCreateHistory(false); + } + String define = defineModel.getDefinition(); + JSONObject definition = JSONObject.parseObject(define); + definition.put("elements", elements); + defineModel.setDefinition(definition.toString()); + defineModel.setUpdateTime(new SimpleDateFormat(CoeDesignerConstant.DATE_TIME_STYLE_YYYY_MM_DD_HH_MM_SS).format(new Date())); + // 保存文件 + LogUtil.appendLog(BatchConst.LOG_START + "保存流程文件", fullLogFile); + CoeDesignerAPIManager.getInstance().storeDefinition(defineModel);// dao操作 + LogUtil.appendLog(BatchConst.LOG_END + "保存流程文件", fullLogFile); + if (relationModelList.size() == 0) { + LogUtil.appendLog(BatchConst.LOG_WARNING + "新增形状属性关联属性内容忽略", simpleLogFile, fullLogFile); + } else { + LogUtil.appendLog(BatchConst.LOG_START + "新增形状属性关联属性内容", simpleLogFile, fullLogFile); + boolean insertProps = relationDao.barchInsert(relationModelList); + if (insertProps) { + for (int i = 0; i < relationModelList.size(); i++) { + String name = relationModelList.get(i).getAttrId(); + String value = relationModelList.get(i).getRelationShapeText(); + + LogUtil.appendLog(BatchConst.LOG_DESC + "形状属性关联属性内容[" + name + "],属性内容值为[" + value + "]", simpleLogFile, fullLogFile); + } + LogUtil.appendLog(BatchConst.LOG_END + "新增形状属性关联属性内容,总共新增[" + relationModelList.size() + "]条", simpleLogFile, fullLogFile); + + } else { + LogUtil.appendLog(BatchConst.LOG_WARNING + "新增形状属性关联属性内容失败,详情查看BPM平台运行日志", simpleLogFile, fullLogFile); + } + } + if (delRelationIdList.size() == 0) { + LogUtil.appendLog(BatchConst.LOG_WARNING + "删除原有形状属性关联属性内容忽略", simpleLogFile, fullLogFile); + } else { + LogUtil.appendLog(BatchConst.LOG_START + "删除原有形状属性关联属性内容", simpleLogFile, fullLogFile); + try { + relationDao.batchDeleteRelationListById(delRelationIdList); + for (int i = 0; i < delRelationIdList.size(); i++) { + String name = delRelationIdList.get(i).getAttrId(); + String value = delRelationIdList.get(i).getRelationShapeText(); + + LogUtil.appendLog(BatchConst.LOG_DESC + "删除原有形状属性关联属性内容[" + name + "],属性内容值为[" + value + "]", simpleLogFile, fullLogFile); + } + LogUtil.appendLog(BatchConst.LOG_END + "删除原有形状属性关联属性内容,总共删除[" + delRelationIdList.size() + "]条", simpleLogFile, fullLogFile); + } catch (SQLException e) { + e.printStackTrace(); + LogUtil.appendLog(BatchConst.LOG_WARNING + "删除原有形状属性关联属性内容失败,详情查看BPM平台运行日志", simpleLogFile, fullLogFile); + } + } + LogUtil.appendLog("导入 " + palModel.getName() + "(v" + palModel.getVersion() + ".0)" + " 流程模型结构[完成]", simpleLogFile, fullLogFile); + // 更新其他自定义属性 + LogUtil.appendLog(BatchConst.LOG_START + "完善模型内形状自定义属性配置", simpleLogFile, fullLogFile); + PALRepositoryAPIManager.getInstance().updateRepositoryProperty(palModel.getId()); + LogUtil.appendLog(BatchConst.LOG_END + "完善模型内形状自定义属性配置", simpleLogFile, fullLogFile); + + LogUtil.appendLog(BatchConst.LOG_END + "[执行阶段][保存模型阶段]", simpleLogFile, fullLogFile); + // 记录成功日志记录 + LogRealTimeCountCache.getCache().get(logId).setSuccessCount(LogRealTimeCountCache.getCache().get(logId).getSuccessCount() + 1); + } + + /** + * 自定义属性 + * @param wsId + * @param palModel + * @param elements + * @param methodAttrsMap + */ + private void handleShapeDefaultAttr(String wsId, PALRepositoryModel palModel, JSONObject elements, Map> methodAttrsMap) { + LogUtil.appendLog(BatchConst.LOG_START + "PAL" + I18nRes.findValue(CoEConstant.APP_ID, palModel.getMethodId()) + "[" + palModel.getName() + "]中形状属性按照属性配置进行属性完善", simpleLogFile, fullLogFile); + for (String key : elements.keySet()) { + JSONObject shape = elements.getJSONObject(key); + if ("linker".equals(shape.getString("name"))) { + continue; + } + String shapeMehtodId = shape.getString("category").replace("_", "."); + String shapeName = shape.getString("name"); + + if (methodAttrsMap.containsKey(palModel.getMethodId()) && methodAttrsMap.containsKey(shapeName)) { + } else { + if (!methodAttrsMap.containsKey(palModel.getMethodId())) { + methodAttrsMap.put(palModel.getMethodId(), new HashMap<>()); + } + JSONObject attrs = ShapeUtil.getProcessUseShapeMethodAttrByShapeName(palModel.getWsId(), shapeMehtodId, palModel.getMethodId(), shapeName); + if (attrs != null) { + methodAttrsMap.get(palModel.getMethodId()).put(shapeName, attrs); + } + } + JSONObject attrs = methodAttrsMap.get(palModel.getMethodId()).get(shapeName);// 最终属性内容 + attrs = JSONObject.parseObject(attrs.toString());// 复制 + JSONArray dataAttributes = shape.getJSONArray("dataAttributes"); + if (!dataAttributes.isEmpty() && dataAttributes.size() > 0) { + for (Object attribute : dataAttributes) { + JSONObject obj = (JSONObject) attribute; + if (obj.containsKey("attributesJsonArray")) { + JSONArray attributesJsonArray = obj.getJSONArray("attributesJsonArray"); + Set attrIds = new HashSet<>(); + for (int i = 0; i < attributesJsonArray.size(); i++) { + if (attributesJsonArray.getJSONObject(i).containsKey("id")) { + attrIds.add(attributesJsonArray.getJSONObject(i).getString("id")); + } + } + for (String attrId : attrs.keySet()) { + if (!attrIds.contains(attrId)) { + JSONObject eleAttrObj = getDefaultAttrObj(attrs.getJSONObject(attrId)); + LogUtil.appendLog(BatchConst.LOG_END + "PAL" + I18nRes.findValue(CoEConstant.APP_ID, palModel.getMethodId()) + "[" + palModel.getName() + "]中形状[" + shape.getString("title") + "][" + shape.getString("text") + "]完善[" + eleAttrObj.getString("name") + "]属性配置", fullLogFile); + attributesJsonArray.add(eleAttrObj); + } + } + } + } + } + } + LogUtil.appendLog(BatchConst.LOG_END + "PAL" + I18nRes.findValue(CoEConstant.APP_ID, palModel.getMethodId()) + "[" + palModel.getName() + "]中形状属性按照属性配置进行属性完善", simpleLogFile, fullLogFile); + } + + /** + * 获取默认属性内容 + * @param attr + * @return + */ + private JSONObject getDefaultAttrObj (JSONObject attr) { + String ref = attr.getString("ref"); + boolean readonly = attr.getBooleanValue("readonly"); + String scope = attr.getString("scope"); + String attrName = attr.getString("title"); + String attrId = attr.getString("id"); + String type = attr.getString("type"); + String groupPath = attr.getString("groupPath"); + String attrKey = attr.getString("key"); + String attrValue = ""; + JSONObject object2 = new JSONObject(); + object2.put("ref", ref); + object2.put("readonly", readonly); + object2.put("scope", scope); + object2.put("name", attrName); + object2.put("id", attrId); + object2.put("type", type); + object2.put("groupPath", groupPath); + object2.put("key", attrKey); + object2.put("value", ""); + return object2; + } + + /** + * 按照模型进行分类 + * @param importData + * @return + */ + private Map>> handleRepositoryData(JSONArray importData) { + Map>> result = new LinkedHashMap<>(); + for (int i = 0; i < importData.size(); i++) { + JSONObject row = importData.getJSONObject(i); + String palId = row.getString("repositoryId"); + String type = row.getString("result");// add/update + String shapeId = row.getString("shapeId"); + if (!result.containsKey(palId)) { + result.put(palId, new HashMap<>()); + } + if (!result.get(palId).containsKey(type)) { + result.get(palId).put(type, new ArrayList<>()); + } + result.get(palId).get(type).add(row); + } + return result; + } + + /** + * 将存在信息错误的内容筛选出去并记录日志 + * @param importData + * @return + */ + private JSONArray handleRowErrData(JSONArray importData) { + JSONArray result = new JSONArray(); + for (int i = 0; i < importData.size(); i++) { + JSONObject row = importData.getJSONObject(i); + if (row.getBooleanValue("isRowOk")) {// 只获取校验通过的数据 + result.add(row); + } else { + LogUtil.appendLog(BatchConst.LOG_WARNING + "校验未通过数据过滤,第[" + (i+1) + "]行数据,错误类型[" + row.getString("result") + "]", simpleLogFile); + LogUtil.appendLog(BatchConst.LOG_WARNING + "校验未通过数据过滤,第[" + (i+1) + "]行数据,错误类型[" + row.getString("result") + "],错误详细信息:" + row, fullLogFile); + } + } + return result; + } + + /** + * 数据校验的结果记录到相关日志,未来如果有需要,可以做界面化输出和Excel输出 + * @param importData + */ + private void recordTableLog(JSONArray importData) { + for (int i = 0; i < importData.size(); i++) { + LogUtil.appendLog(importData.getJSONObject(i).toString(), checkTableFile); + } + } + + /** + * 计算使用时间 + * @param endTime + * @param startTime + * @return + */ + private String takeTime(long endTime, long startTime) { + long time = endTime - startTime; + String timeMsg = ""; + if (time > 1000 * 60) { + timeMsg = "[" + (time / 1000 / 60) + "]分钟"; + } else if (time > 1000) { + timeMsg = "[" + (time / 1000) + "]秒"; + } else { + timeMsg = "[" + time + "]毫秒"; + } + return timeMsg; + } + + /** + * 设置所有连线 + * @param newElements + * @param shapeRowCount + * @return + */ + private JSONArray setElementLinkersJSONArray(JSONArray newElements, int shapeRowCount, int maxZIndex) { + JSONArray result = new JSONArray(); + int zindex = maxZIndex + 1; + int count = 0; + if (newElements.size() > 1) { + for (int i = 0; i < newElements.size() - 1; i++) { + count++; + boolean isNewRow = false; + if (count % shapeRowCount == 0) { + isNewRow = true; + } + JSONObject fromShape = newElements.getJSONObject(i); + JSONObject toShape = newElements.getJSONObject(i+1); + String fromId = fromShape.getString("id"); + String toId = toShape.getString("id"); + JSONObject shape = JSONObject.parseObject(linkerDef); + JSONObject linker = JSON.parseObject(shape.toString()); + String shapeId = UUIDGener.getObjectId();//连线id + linker.put("id", shapeId); + JSONObject fromProps = fromShape.getJSONObject("props"); + JSONObject toProps = toShape.getJSONObject("props"); + int fromX = validateJson(fromProps.getInteger("x")); + int fromY = validateJson(fromProps.getInteger("y")); + int fromW = validateJson(fromProps.getInteger("w")); + int fromH = validateJson(fromProps.getInteger("h")); + int toX = validateJson(toProps.getInteger("x")); + int toY = validateJson(toProps.getInteger("y")); + int toW = validateJson(toProps.getInteger("w")); + int toH = validateJson(toProps.getInteger("h")); + JSONArray fromAnchors = fromShape.getJSONArray("anchors"); + int fromRightX = getRightX(fromAnchors, fromW, fromH); + JSONArray toAnchors = toShape.getJSONArray("anchors"); + int toLeftX = getLeftX(toAnchors, toW, toH); + JSONObject from = new JSONObject(); + JSONObject to = new JSONObject(); + if (isNewRow) { + from.put("x", fromX + fromW / 2); + from.put("y", fromY + fromH); + from.put("angle", 4.71238898038469); + to.put("x", toX + toW / 2); + to.put("y", toY); + to.put("angle", 1.5707964); + + JSONArray points = new JSONArray(); + JSONObject point1 = new JSONObject(); + point1.put("x", validateJson(from.getInteger("x"))); + point1.put("y", (validateJson(from.getInteger("y")) + validateJson(to.getInteger("y"))) / 2); + points.add(point1); + JSONObject point2 = new JSONObject(); + point2.put("x", validateJson(to.getInteger("x"))); + point2.put("y", (validateJson(from.getInteger("y")) + validateJson(to.getInteger("y"))) / 2); + points.add(point2); + linker.put("points", points); + } else { + from.put("x", fromX + fromRightX); + from.put("y", fromY + fromH / 2); + from.put("angle", 3.141592653589793); + to.put("x", toX + toLeftX); + to.put("y", toY + toH / 2); + to.put("angle", 0); + + JSONArray points = new JSONArray(); + JSONObject point1 = new JSONObject(); + point1.put("x", (validateJson(from.getInteger("x")) + validateJson(to.getInteger("x"))) / 2); + point1.put("y", validateJson(to.getInteger("y"))); + points.add(point1); + JSONObject point2 = new JSONObject(); + point2.put("x", (validateJson(from.getInteger("x")) + validateJson(to.getInteger("x"))) / 2); + point2.put("y", validateJson(to.getInteger("y"))); + points.add(point2); + linker.put("points", points); + } + + from.put("id", fromShape.getString("id")); + to.put("id", toShape.getString("id")); + JSONObject props = new JSONObject(); + props.put("zindex", zindex); + linker.put("props", props); + linker.put("from", from); + linker.put("to", to); + result.add(linker); + zindex++; + } + } + return result; + } + + private int getLeftX(JSONArray toAnchors, int w, int h) { + int minX = 99999; + for (int i = 0; i < toAnchors.size(); i++) { + String strX = toAnchors.getJSONObject(i).getString("x").replace("w", w + "").replace("h", h + "").replace("Mat" + h, "Math"); + double x = Double.parseDouble(runJs(strX)); + minX = minX < (int) x ? minX : (int) x; + } + return minX; + } + + private int getRightX(JSONArray fromAnchors, int w, int h) { + int maxX = -999; + for (int i = 0; i < fromAnchors.size(); i++) { + String strX = fromAnchors.getJSONObject(i).getString("x").replace("w", w + "").replace("h", h + "").replace("Mat" + h, "Math"); + double x = Double.parseDouble(runJs(strX)); + maxX = maxX > (int) x ? maxX : (int) x; + } + return maxX; + } + + /** + * 创建具有合理位置的节点数据 + * + * @param elements + * @param shapeRowCount + * @return + */ + private JSONArray getMethodElementsJSONArray(JSONArray elements, int shapeRowCount, int maxZIndex, int initY) { + JSONArray result = new JSONArray(); + int zindex = maxZIndex; + int initX = 0; + int pageEdge = 100; + int count = 0; + initX += pageEdge; + initY += pageEdge; + if (maxZIndex > 0) {// 在已有图的基础上增加的形状,缩小默认的纵轴距离高度 + initY = initY - pageEdge; + } + for (int i = 0; i < elements.size(); i++) { + JSONObject shape = elements.getJSONObject(i); + count++; + if (count % (shapeRowCount+1) == 0) { + count = 1; + initY += 90; + // 换行 + initX = 0; + initX = pageEdge + initX; + } + zindex++; + if (shape.containsKey("dataAttributes")) { + JSONArray dataAttributes = JSONArray.parseArray(shape.getString("dataAttributes")); + for (int index = 0; index < dataAttributes.size(); index++) { + dataAttributes.getJSONObject(index).put("id", UUIDGener.getObjectId()); + } + shape.put("dataAttributes", dataAttributes); + } + int totalWidth = 160;// 每个节点总宽度,空白+节点+空白 + int totalHeight = 200;// 每个节点总高度,空白+节点+空白 + int x = 0; + int y = 0; + int w = validateJson(shape.getJSONObject("props").getInteger("w")); + int h = validateJson(shape.getJSONObject("props").getInteger("h")); + int leftBlankWidth = (totalWidth - w)/2; + int topBlankHeight = (totalHeight - h)/2; + x = initX + leftBlankWidth; + initX = x + w + leftBlankWidth; + y = initY + topBlankHeight; +// y = pageEdge + initY; +// if (y < 0) { +// y = 100; +// } + JSONObject props = shape.getJSONObject("props"); + props.put("x", x); + props.put("y", y); + props.put("zindex", zindex); + shape.put("props", props); + result.add(shape); + } + return result; + } + + private int validateJson(Integer index) { + return index == null ? 0 : index; + } + + /** + * 转换为js + * + * @param val + * @return string + */ + private static String runJs(String val) { + String jsVal = ""; + try { + Context cx = Context.enter(); + Scriptable scope = cx.initStandardObjects(); + Object result = cx.evaluateString(scope, val, null, 1, null); + jsVal = Context.toString(result); + } finally { + Context.exit(); + } + return jsVal; + } + +} diff --git a/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/ShapeConst.java b/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/ShapeConst.java index ff2dc11a..949e3528 100644 --- a/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/ShapeConst.java +++ b/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/ShapeConst.java @@ -4,6 +4,7 @@ public class ShapeConst { // Excel工作表sheet页名称 public final static String SHEET_NAME_SUFFIX = "模型形状清单"; + public final static String SHEET_NAME_IMPORT_SUFFIX = "模型导入清单"; public final static String SHEET_HELPER = "说明"; // 扩展属性名称前后缀 @@ -16,6 +17,8 @@ public class ShapeConst { public final static String TABLE_REPOSITORY_TYPE = "模型类型"; public final static String TABLE_SHAPE_NAME = "形状名称"; public final static String TABLE_SHAPE_TYPE = "形状类型"; + public final static String TABLE_SHAPE_BRANCH = "形状分支"; + public final static String TABLE_SHAPE_NUM = "形状编号"; public final static String TABLE_EXTAND_EXAMPLE = "扩展"; public final static String TABLE_EXTAND_EXAMPLE2 = "..."; @@ -23,4 +26,17 @@ public class ShapeConst { public final static String [] SHAPE_TITLE_ROW = new String [] {TABLE_REPOSITORY_NAME, TABLE_REPOSITORY_TYPE, TABLE_SHAPE_NAME, TABLE_SHAPE_TYPE}; public final static String SHAPE_BASE_TITLE_ROW = "模型名称、模型类型、形状名称、形状类型"; + public final static String [] SHAPE_TITLE_ROW_IMPORT = new String [] {TABLE_REPOSITORY_NAME, TABLE_REPOSITORY_TYPE, TABLE_SHAPE_NAME, TABLE_SHAPE_TYPE,TABLE_SHAPE_BRANCH,TABLE_SHAPE_NUM}; + public final static String SHAPE_BASE_TITLE_ROW_IMPORT = "模型名称、模型类型、形状名称、形状类型、形状分支、形状编号"; + + + public final static Integer SHAPE_NODE_WIDTH = 200; + public final static Integer SHAPE_NODE_HEIGHT = 70; + + + public final static Integer SHAPE_NODE_INTERVAL = 50; + public final static Integer SHAPE_HEIGHT_INTERVAL = 100; + + public final static Integer SHAPE_BRANCH_INTERVAL = 500; + } diff --git a/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/ShapeUtil.java b/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/ShapeUtil.java index b426a92e..a6e8ec00 100644 --- a/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/ShapeUtil.java +++ b/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/ShapeUtil.java @@ -19,6 +19,9 @@ public class ShapeUtil { public static String getModelShapeListName(String methodCategory) { return I18nRes .findValue(CoEConstant.APP_ID, methodCategory) + ShapeConst.SHEET_NAME_SUFFIX; } + public static String getModelShapeImportName(String methodCategory) { + return I18nRes.findValue(CoEConstant.APP_ID, methodCategory) + ShapeConst.SHEET_NAME_IMPORT_SUFFIX; + } /** * BPMN图并不全部使用,给定范围 diff --git a/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/ValidShapeExcel.java b/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/ValidShapeExcel.java index 10f7be5b..daeb7e31 100644 --- a/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/ValidShapeExcel.java +++ b/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/ValidShapeExcel.java @@ -17,6 +17,8 @@ import com.actionsoft.apps.coe.pal.cooperation.CoeCooperationAPIManager; import com.actionsoft.apps.coe.pal.pal.method.cache.PALMethodCache; import com.actionsoft.apps.coe.pal.pal.method.model.PALMethodModel; import com.actionsoft.apps.coe.pal.pal.repository.cache.PALRepositoryCache; +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.PALRepositoryModel; import com.actionsoft.i18n.I18nRes; @@ -61,6 +63,12 @@ public class ValidShapeExcel { String sheetName = ShapeUtil.getModelShapeListName(methodCategory); XSSFSheet sheet = wb.getSheet(sheetName); if (sheet == null) { + //模型导入 入口 + String sheetName1 = ShapeUtil.getModelShapeImportName(methodCategory); + XSSFSheet sheet1 = wb.getSheet(sheetName1); + if (null != sheet1){ + return this.checkShapeImportList(uc, file, wsId, teamId, methodCategory); + } return ResponseObject.newErrResponse(errMsg + "上传文件中【" + sheetName + "】工作表不存在"); } List titleList = new LinkedList(); @@ -96,6 +104,50 @@ public class ValidShapeExcel { return ro; } + public ResponseObject checkShapeImportList(UserContext uc, File file, String wsId, String teamId, String methodCategory) { + XSSFWorkbook wb = POIUtil.getWorkbook(file); + if (wb == null) { + return ResponseObject.newErrResponse(errMsg + "获取上传文件失败"); + } + + String sheetName = ShapeUtil.getModelShapeImportName(methodCategory); + XSSFSheet sheet = wb.getSheet(sheetName); + if (sheet == null) { + return ResponseObject.newErrResponse(errMsg + "上传文件中【" + sheetName + "】工作表不存在"); + } + List titleList = new LinkedList(); + XSSFRow titleRow = sheet.getRow(0); + if (titleRow == null ) { + return ResponseObject.newErrResponse(errMsg + "上传文件工作表中首行为标题行,不能为空,请调整"); + } + int cellNum = titleRow.getLastCellNum(); + for (int i = 0; i < cellNum; i++) { + XSSFCell cell = titleRow.getCell(i); + String title = POIUtil.getCellValueByCell(cell); + if (UtilString.isEmpty(title)) { + break; + } + titleList.add(title); + } + if (titleList.size() == 0) { + return ResponseObject.newErrResponse(errMsg + "上传文件工作表中首行为标题行,不能为空,请调整"); + } + // 校验标题行 + ResponseObject checkTitleRo = checkTitleRowImport(wsId, titleList, methodCategory); + if (!checkTitleRo.isOk()) { + return checkTitleRo; + } + // 构造Excel数据model + List excelShapeModels = handleImportExcel2Model(sheet, titleList); + ResponseObject ro = ResponseObject.newOkResponse(); + // 获取所有数据 + JSONObject result = new JSONObject(); + result.put("titleRow", titleList); + result.put("data", checkImportData(wsId, teamId, methodCategory, uc, excelShapeModels, titleList)); + ro.put("data", result); + return ro; + } + /** * Excel中数据转换为model处理 * @param sheet @@ -131,6 +183,47 @@ public class ValidShapeExcel { return result; } + /** + * Excel中数据转换为model处理 + * @param sheet + * @param titleList + * @return + */ + private List handleImportExcel2Model(XSSFSheet sheet, List titleList) { + List result = new ArrayList<>(); + // 获取所有Excel数据 + List> dataList = getDataList(sheet, titleList); + // Excel内容转换为Model + int row = 1; + for (List rowDataList : dataList) { + // 0,模型名称 + String repositoryName = rowDataList.get(0); + // 1,模型类型 + String repositoryType = rowDataList.get(1); + // 2,形状名称 + String shapeName = rowDataList.get(2); + // 3,形状类型 + String shapeType = rowDataList.get(3); + // 4,形状分支 + String shapeBranch = rowDataList.get(4); + // 5,形状编号 + String shapeNo = rowDataList.get(5); + // 6,扩展属性 + List shapeRowList = new ArrayList<>(rowDataList.stream().collect(Collectors.toList())); + ExcelShapeModel excelShapeModel = new ExcelShapeModel(); + excelShapeModel.setRow(row++); + excelShapeModel.setRepositoryName(repositoryName); + excelShapeModel.setRepositoryType(repositoryType); + excelShapeModel.setShapeName(shapeName); + excelShapeModel.setShapeType(shapeType); + excelShapeModel.setShapeBranch(shapeBranch); + excelShapeModel.setShapeNo(shapeNo); + excelShapeModel.setRowData(shapeRowList); + result.add(excelShapeModel); + } + return result; + } + /** * 校验数据 * @param wsId @@ -610,6 +703,578 @@ public class ValidShapeExcel { } + /** + * 校验数据 + * @param wsId + * @param teamId + * @param methodCategory + * @param uc + * @param excelShapeModels + * @param titleList + * @return + */ + private JSONObject checkImportData(String wsId, String teamId, String methodCategory, UserContext uc, List excelShapeModels, List titleList) { + Iterator iterator = excelShapeModels.iterator(); + // 1. 过滤掉关键信息空白的数据(模型名称、模型类型、形状名称、形状类型、形状分支、形状编号任一为空即满足过滤条件) + List blankList = new ArrayList(); + while (iterator.hasNext()) { + ExcelShapeModel row = iterator.next(); + String repositoryName = row.getRepositoryName(); + String repositoryType = row.getRepositoryType(); + String shapeName = row.getShapeName(); + String shapeType = row.getShapeType(); + String shapeBranch = row.getShapeBranch(); + String shapeNo = row.getShapeNo(); + // 校验模型名称、模型类型、形状名称、形状类型、形状分支、形状编号任一为空 + if (UtilString.isEmpty(repositoryName) || UtilString.isEmpty(repositoryType) + || UtilString.isEmpty(shapeName) || UtilString.isEmpty(shapeType) + || UtilString.isEmpty(shapeBranch) || UtilString.isEmpty(shapeNo)) { + RepositoryShapeInfoModel blankModel = new RepositoryShapeInfoModel(); + blankModel.setRepositoryName(repositoryName); + blankModel.setMethodName(repositoryType); + blankModel.setShapeName(shapeName); + blankModel.setShapeType(shapeType); + blankModel.setShapeBranch(shapeBranch); + blankModel.setShapeNo(shapeNo); + blankModel.setExcelShapeModel(row); + blankModel.setResult("blank"); + blankModel.setRowOk(false); + blankModel.setRowMsg(ShapeConst.SHAPE_BASE_TITLE_ROW_IMPORT + "不允许为空"); + blankList.add(blankModel); + iterator.remove(); + } + } + // 2.过滤掉Excel中的重复数据记录(模型名称、模型类型、形状名称、形状类型、形状分支、形状编号四项内容完全重复) + List excelRepeatList = new ArrayList<>(); + Map tmpMap = new HashMap<>(); + iterator = excelShapeModels.iterator(); + while (iterator.hasNext()) { + ExcelShapeModel row = iterator.next(); + String repositoryName = row.getRepositoryName(); + String repositoryType = row.getRepositoryType(); + String shapeName = row.getShapeName(); + String shapeType = row.getShapeType(); + String shapeBranch = row.getShapeBranch(); + String shapeNo = row.getShapeNo(); + String key = repositoryName + "|" + repositoryType + "|" + shapeName + "|" + shapeType+ "|" + shapeBranch+ "|" + shapeNo; + if (tmpMap.containsKey(key)) { + RepositoryShapeInfoModel repeatModel = new RepositoryShapeInfoModel(); + repeatModel.setRepositoryName(repositoryName); + repeatModel.setMethodName(repositoryType); + repeatModel.setShapeName(shapeName); + repeatModel.setShapeType(shapeType); + repeatModel.setShapeBranch(shapeBranch); + repeatModel.setShapeNo(shapeNo); + repeatModel.setExcelShapeModel(row); + repeatModel.setResult("repeat"); + repeatModel.setRowOk(false); + repeatModel.setRowMsg("与第" + tmpMap.get(key) + "行重复"); + excelRepeatList.add(repeatModel); + iterator.remove(); + } else { + tmpMap.put(key, row.getRow()); + } + } + + // 获取PAL模型信息(多版本只取使用中版本) + List inuseRepositoryList = ProcessUtil.getInuseRepositoryList(wsId, methodCategory); + Map repositoryMap = new HashMap<>();// 按照名称+建模分类名称记录对应id + Map repeatNameCountMap = new HashMap<>();// 统计名称重复的 + for (PALRepositoryModel model : inuseRepositoryList) { + String key = model.getName() + "|||" + I18nRes.findValue(CoEConstant.APP_ID, model.getMethodId()); + repositoryMap.put(key, model.getId()); + if (!repeatNameCountMap.containsKey(key)) { + repeatNameCountMap.put(key, 0); + } + repeatNameCountMap.put(key, repeatNameCountMap.get(key) + 1); + } + // 3.模型没有匹配上 + List noMatchList = new ArrayList<>(); + iterator = excelShapeModels.iterator(); + while (iterator.hasNext()) { + ExcelShapeModel row = iterator.next(); + String repositoryName = row.getRepositoryName(); + String repositoryType = row.getRepositoryType(); + String shapeName = row.getShapeName(); + String shapeType = row.getShapeType(); + String shapeBranch = row.getShapeBranch(); + String shapeNo = row.getShapeNo(); + String key = repositoryName + "|||" + repositoryType; + if (!repositoryMap.containsKey(key)) { + RepositoryShapeInfoModel noMatchModel = new RepositoryShapeInfoModel(); + noMatchModel.setRepositoryName(repositoryName); + noMatchModel.setMethodName(repositoryType); + noMatchModel.setShapeName(shapeName); + noMatchModel.setShapeType(shapeType); + noMatchModel.setShapeBranch(shapeBranch); + noMatchModel.setShapeNo(shapeNo); + noMatchModel.setExcelShapeModel(row); + noMatchModel.setResult("noMatch"); + noMatchModel.setRowOk(false); + noMatchModel.setRowMsg("PAL中不存在对应的模型"); + noMatchList.add(noMatchModel); + iterator.remove(); + } + } + + // 4.模型没有写权限 + List noPermList = new ArrayList<>(); + if (!UtilString.isEmpty(teamId)) { + iterator = excelShapeModels.iterator(); + Set permVerIds = BatchUtil.getPermVersionIds(wsId, teamId, uc.getUID()); + while (iterator.hasNext()) { + ExcelShapeModel row = iterator.next(); + String repositoryName = row.getRepositoryName(); + String repositoryType = row.getRepositoryType(); + String shapeName = row.getShapeName(); + String shapeType = row.getShapeType(); + String shapeBranch = row.getShapeBranch(); + String shapeNo = row.getShapeNo(); + String key = repositoryName + "|||" + repositoryType; + String palId = repositoryMap.get(key); + PALRepositoryModel plModel = PALRepositoryCache.getCache().get(palId); + BaseModel defineModel = CoeDesignerAPIManager.getInstance().getDefinition(plModel.getId(), 0); + String define = defineModel.getDefinition(); + JSONObject definition = JSON.parseObject(define); + JSONObject elements = definition.getJSONObject("elements"); + + if (!permVerIds.contains(plModel.getVersionId())) { + RepositoryShapeInfoModel noPermModel = new RepositoryShapeInfoModel(); + noPermModel.setRepositoryName(repositoryName); + noPermModel.setMethodName(repositoryType); + noPermModel.setShapeName(shapeName); + noPermModel.setShapeType(shapeType); + noPermModel.setShapeBranch(shapeBranch); + noPermModel.setShapeNo(shapeNo); + noPermModel.setExcelShapeModel(row); + noPermModel.setResult("noPerm"); + noPermModel.setRowOk(false); + noPermModel.setRowMsg("没有对应的数据编辑权限"); + noPermList.add(noPermModel); + iterator.remove(); + }else if (null == elements || elements.isEmpty()){ + RepositoryShapeInfoModel noPermModel = new RepositoryShapeInfoModel(); + noPermModel.setRepositoryName(repositoryName); + noPermModel.setMethodName(repositoryType); + noPermModel.setShapeName(shapeName); + noPermModel.setShapeType(shapeType); + noPermModel.setShapeBranch(shapeBranch); + noPermModel.setShapeNo(shapeNo); + noPermModel.setExcelShapeModel(row); + noPermModel.setResult("noPerm"); + noPermModel.setRowOk(false); + noPermModel.setRowMsg("模型已存在形状信息"); + noPermList.add(noPermModel); + iterator.remove(); + } + } + } + + //已存在形状模型没有权限 + iterator = excelShapeModels.iterator(); + while (iterator.hasNext()) { + ExcelShapeModel row = iterator.next(); + String repositoryName = row.getRepositoryName(); + String repositoryType = row.getRepositoryType(); + String shapeName = row.getShapeName(); + String shapeType = row.getShapeType(); + String shapeBranch = row.getShapeBranch(); + String shapeNo = row.getShapeNo(); + String key = repositoryName + "|||" + repositoryType; + String palId = repositoryMap.get(key); + PALRepositoryModel plModel = PALRepositoryCache.getCache().get(palId); + BaseModel defineModel = CoeDesignerAPIManager.getInstance().getDefinition(plModel.getId(), 0); + String define = defineModel.getDefinition(); + JSONObject definition = JSON.parseObject(define); + JSONObject elements = definition.getJSONObject("elements"); + if (null != elements && !elements.isEmpty()){ + RepositoryShapeInfoModel noPermModel = new RepositoryShapeInfoModel(); + noPermModel.setRepositoryName(repositoryName); + noPermModel.setMethodName(repositoryType); + noPermModel.setShapeName(shapeName); + noPermModel.setShapeType(shapeType); + noPermModel.setShapeBranch(shapeBranch); + noPermModel.setShapeNo(shapeNo); + noPermModel.setExcelShapeModel(row); + noPermModel.setResult("noPerm"); + noPermModel.setRowOk(false); + noPermModel.setRowMsg("模型已存在形状信息"); + noPermList.add(noPermModel); + iterator.remove(); + } + } + + + // 5.模型出现了多个匹配 + List moreMatchList = new ArrayList<>(); + iterator = excelShapeModels.iterator(); + while (iterator.hasNext()) { + ExcelShapeModel row = iterator.next(); + String repositoryName = row.getRepositoryName(); + String repositoryType = row.getRepositoryType(); + String shapeName = row.getShapeName(); + String shapeType = row.getShapeType(); + String shapeBranch = row.getShapeBranch(); + String shapeNo = row.getShapeNo(); + String key = repositoryName + "|||" + repositoryType; + String palId = repositoryMap.get(key); + PALRepositoryModel plModel = PALRepositoryCache.getCache().get(palId); + if (repeatNameCountMap.get(key) > 1) { + RepositoryShapeInfoModel moreMatchModel = new RepositoryShapeInfoModel(); + moreMatchModel.setRepositoryId(palId); + moreMatchModel.setRepositoryName(repositoryName); + moreMatchModel.setMethodName(repositoryType); + moreMatchModel.setMethodId(plModel.getMethodId()); + moreMatchModel.setShapeName(shapeName); + moreMatchModel.setShapeType(shapeType); + moreMatchModel.setShapeBranch(shapeBranch); + moreMatchModel.setShapeNo(shapeNo); + moreMatchModel.setExcelShapeModel(row); + moreMatchModel.setResult("moreMatch"); + moreMatchModel.setRowOk(false); + moreMatchModel.setRowMsg("出现PAL多个符合条件的模型"); + moreMatchList.add(moreMatchModel); + iterator.remove(); + } + } + // 6.存在模型为只读的 + List readonlyList = new ArrayList<>(); + iterator = excelShapeModels.iterator(); + while (iterator.hasNext()) { + ExcelShapeModel row = iterator.next(); + String repositoryName = row.getRepositoryName(); + String repositoryType = row.getRepositoryType(); + String shapeName = row.getShapeName(); + String shapeType = row.getShapeType(); + String shapeBranch = row.getShapeBranch(); + String shapeNo = row.getShapeNo(); + String key = repositoryName + "|||" + repositoryType; + String palId = repositoryMap.get(key); + PALRepositoryModel plModel = PALRepositoryCache.getCache().get(palId); + if (plModel.isPublish() || plModel.isApproval() || plModel.isApproval()) {// 已发布、审批中、停用则记录不更新 + String status = plModel.isPublish() ? "已发布" : plModel.isApproval() ? "审批中" : "已停用"; + RepositoryShapeInfoModel readonlyModel = new RepositoryShapeInfoModel(); + readonlyModel.setRepositoryId(palId); + readonlyModel.setRepositoryName(repositoryName); + readonlyModel.setMethodName(repositoryType); + readonlyModel.setMethodId(plModel.getMethodId()); + readonlyModel.setShapeName(shapeName); + readonlyModel.setShapeType(shapeType); + readonlyModel.setShapeBranch(shapeBranch); + readonlyModel.setShapeNo(shapeNo); + readonlyModel.setExcelShapeModel(row); + readonlyModel.setResult("readonly"); + readonlyModel.setRowOk(false); + readonlyModel.setRowMsg("模型" + status + "不可编辑"); + readonlyList.add(readonlyModel); + iterator.remove(); + } + } + + // 查询一些形状定义 + /*Map> shapeObjMap = new HashMap<>();// 形状定义信息 + Map> shapeMap = new HashMap<>();// 形状名称类型与id的映射关系 + // 剩下的数据先获取下形状信息,做进一步判断 + iterator = excelShapeModels.iterator(); + while (iterator.hasNext()) { + ExcelShapeModel row = iterator.next(); + String repositoryName = row.getRepositoryName(); + String repositoryType = row.getRepositoryType(); + String key = repositoryName + "|||" + repositoryType; + String palId = repositoryMap.get(key); + PALRepositoryModel plModel = PALRepositoryCache.getCache().get(palId); + List shapeList = CoeDesignerUtil.getShapeMessageJson5(palId); + shapeObjMap.put(key, shapeList); + }*/ + + // 形状名称+类型的数量统计 key:key,value:key:shapeName+shapeType,value:count + /*Map> sameShapeMap = new HashMap<>(); + for (Map.Entry> entry : shapeObjMap.entrySet()) { + String key = entry.getKey(); + List shapeList = entry.getValue(); + for (JSONObject shapeObj : shapeList) { + String shapeId = shapeObj.getString("id"); + String shapeName = com.actionsoft.apps.coe.pal.pal.repository.designer.util.ShapeUtil.replaceBlank(shapeObj.getString("text")).replace(" ", ""); + String shapeType = com.actionsoft.apps.coe.pal.pal.repository.designer.util.ShapeUtil.replaceBlank(shapeObj.getString("title")).replace(" ", ""); + String shapeKey = shapeName + "|||" + shapeType; + // 形状名称+类型与对应的形状id映射记录 + if (!shapeMap.containsKey(key)) { + shapeMap.put(key, new HashMap<>()); + } + shapeMap.get(key).put(shapeKey, shapeId); + + // 形状名称+类型的数量记录 + if (!sameShapeMap.containsKey(key)) { + sameShapeMap.put(key, new HashMap<>()); + } + if (!sameShapeMap.get(key).containsKey(shapeKey)) { + sameShapeMap.get(key).put(shapeKey, 0); + } + sameShapeMap.get(key).put(shapeKey, sameShapeMap.get(key).get(shapeKey) + 1); + } + }*/ + + // 7.模型形状存在但是出现了多个匹配 + // 借用moreMatchList,不再创建新的,统一归为匹配出现多个类型 + /*iterator = excelShapeModels.iterator(); + while (iterator.hasNext()) { + ExcelShapeModel row = iterator.next(); + String repositoryName = row.getRepositoryName(); + String repositoryType = row.getRepositoryType(); + String shapeName = row.getShapeName(); + String shapeType = row.getShapeType(); + String key = repositoryName + "|||" + repositoryType; + String palId = repositoryMap.get(key); + PALRepositoryModel plModel = PALRepositoryCache.getCache().get(palId); + String shapeKey = shapeName + "|||" + shapeType; + if (sameShapeMap.containsKey(key) && sameShapeMap.get(key).containsKey(shapeKey) && sameShapeMap.get(key).get(shapeKey) > 1) { + RepositoryShapeInfoModel moreMatchModel = new RepositoryShapeInfoModel(); + moreMatchModel.setRepositoryId(palId); + moreMatchModel.setRepositoryName(repositoryName); + moreMatchModel.setMethodName(repositoryType); + moreMatchModel.setMethodId(plModel.getMethodId()); + moreMatchModel.setShapeName(shapeName); + moreMatchModel.setShapeType(shapeType); + moreMatchModel.setExcelShapeModel(row); + moreMatchModel.setResult("moreMatch"); + moreMatchModel.setRowOk(false); + moreMatchModel.setRowMsg("出现PAL多个符合条件的模型形状"); + moreMatchList.add(moreMatchModel); + iterator.remove(); + } + }*/ + + // 剩下的都是基本信息校验通过的 + List matchShapeList = new ArrayList<>(); + iterator = excelShapeModels.iterator(); + while (iterator.hasNext()) { + ExcelShapeModel row = iterator.next(); + String repositoryName = row.getRepositoryName(); + String repositoryType = row.getRepositoryType(); + String shapeName = row.getShapeName(); + String shapeType = row.getShapeType(); + String shapeBranch = row.getShapeBranch(); + String shapeNo = row.getShapeNo(); + String key = repositoryName + "|||" + repositoryType; + String palId = repositoryMap.get(key); + PALRepositoryModel plModel = PALRepositoryCache.getCache().get(palId); + String shapeKey = shapeName + "|||" + shapeType; + // 8.模型形状需要新增 + String result = "add"; + String shapeId = ""; +// if (shapeMap.containsKey(key) && shapeMap.get(key).containsKey(shapeKey)) { +// // 9.模型形状需要更新 +// shapeId = shapeMap.get(key).get(shapeKey); +// result = "update"; +// } + RepositoryShapeInfoModel shapeModel = new RepositoryShapeInfoModel(); + shapeModel.setRepositoryId(palId); + shapeModel.setRepositoryName(repositoryName); + shapeModel.setMethodName(repositoryType); + shapeModel.setMethodId(plModel.getMethodId()); + shapeModel.setShapeName(shapeName); + shapeModel.setShapeType(shapeType); + shapeModel.setExcelShapeModel(row); + shapeModel.setResult(result); + shapeModel.setRowOk(true); + shapeModel.setRowMsg(""); + matchShapeList.add(shapeModel); + } + // 10.校验属性 + for (int i = 0; i < matchShapeList.size(); i++) { + RepositoryShapeInfoModel model = matchShapeList.get(i); + ExcelShapeModel row = model.getExcelShapeModel(); + String repositoryName = model.getRepositoryName(); + String methodId = model.getMethodId(); + String shapeName = model.getShapeName(); + String shapeType = model.getShapeType(); + String shapeBranch = model.getShapeBranch(); + String shapeNo = model.getShapeNo(); + String shapeId = model.getShapeId(); + String key = repositoryName + "|||" + methodId; + String palId = repositoryMap.get(key); + JSONArray rowJson = new JSONArray(); + List rowDataList = row.getRowData(); + for (int j = 0; j < rowDataList.size(); j++) { + String title = titleList.get(j); + String cellValue = rowDataList.get(j); + // ****这里面要把所有的列都写全,不然界面的表格会出现列偏移**** + if (ShapeConst.TABLE_REPOSITORY_NAME.equals(title)) { + JSONObject o = new JSONObject(); + o.put("name", ShapeConst.TABLE_REPOSITORY_NAME); + o.put("name2", ShapeConst.TABLE_REPOSITORY_NAME); + o.put("value", BatchUtil.specialCharTransfer(cellValue)); + o.put("isOk", true); + o.put("msg", ""); + rowJson.add(o); + } else if (ShapeConst.TABLE_REPOSITORY_TYPE.equals(title)) { + JSONObject o = new JSONObject(); + o.put("name", ShapeConst.TABLE_REPOSITORY_TYPE); + o.put("name2", ShapeConst.TABLE_REPOSITORY_TYPE); + o.put("value", BatchUtil.specialCharTransfer(cellValue)); + o.put("isOk", true); + o.put("msg", ""); + rowJson.add(o); + } else if (ShapeConst.TABLE_SHAPE_NAME.equals(title)) { + JSONObject param = new JSONObject(); + param.put("value", cellValue); + param.put("wsId", wsId); + rowJson.add(JSONObject.parseObject(new ValidShape(new ValidShapeName()).execute(param).toString())); + } else if (ShapeConst.TABLE_SHAPE_TYPE.equals(title)) { + JSONObject o = new JSONObject(); + o.put("name", ShapeConst.TABLE_SHAPE_TYPE); + o.put("name2", ShapeConst.TABLE_SHAPE_TYPE); + o.put("value", BatchUtil.specialCharTransfer(cellValue)); + o.put("isOk", true); + o.put("msg", ""); + rowJson.add(o); + }else if (ShapeConst.TABLE_SHAPE_BRANCH.equals(title)) { + JSONObject o = new JSONObject(); + o.put("name", ShapeConst.TABLE_SHAPE_BRANCH); + o.put("name2", ShapeConst.TABLE_SHAPE_BRANCH); + o.put("value", BatchUtil.specialCharTransfer(cellValue)); + o.put("isOk", true); + o.put("msg", ""); + rowJson.add(o); + }else if (ShapeConst.TABLE_SHAPE_NUM.equals(title)) { + JSONObject o = new JSONObject(); + o.put("name", ShapeConst.TABLE_SHAPE_NUM); + o.put("name2", ShapeConst.TABLE_SHAPE_NUM); + o.put("value", BatchUtil.specialCharTransfer(cellValue)); + o.put("isOk", true); + o.put("msg", ""); + rowJson.add(o); + } else {// 扩展属性 + String propertyName = title.substring(title.indexOf("扩展<") + 3, title.lastIndexOf(">")); + JSONObject methodAttrs = queryMethodAttrs(wsId, methodId, shapeType); + if (methodAttrs.containsKey(propertyName)) { + // 校验各种类型 + JSONObject attr = methodAttrs.getJSONObject(propertyName); + String attrType = attr.getString("type"); + JSONObject param = new JSONObject(); + param.put("title", propertyName); + param.put("attr", attr); + param.put("value", cellValue); + param.put("wsId", wsId); + if ("string".equals(attrType) || "textarea".equals(attrType)) {// 文本 + rowJson.add(JSONObject.parseObject(new ValidShape(new ValidShapeString()).execute(param).toString())); + } else if ("relation".equals(attrType)) {// 关联 + rowJson.add(JSONObject.parseObject(new ValidShape(new ValidShapeRelation()).execute(param).toString())); + } else if ("awsorg".equals(attrType)) {// 关联AWS平台 + rowJson.add(JSONObject.parseObject(new ValidShape(new ValidShapeAwsOrg()).execute(param).toString())); + } else if ("select_m".equals(attrType) || "select".equals(attrType)) {// 单多选 + rowJson.add(JSONObject.parseObject((new ValidShape(new ValidShapeSelect()).execute(param).toString()))); + } else {// 其他,按照string对待 + rowJson.add(JSONObject.parseObject(new ValidShape(new ValidShapeString()).execute(param).toString())); + } + } else { + JSONObject param = new JSONObject(); + param.put("title", propertyName); + param.put("attr", "tmp"); + param.put("value", ""); + param.put("wsId", wsId); + rowJson.add(JSONObject.parseObject(new ValidShape(new ValidShapeString()).execute(param).toString())); + } + } + } + model.setCheckResult(rowJson); + } + // 整理最终结果 + List allDataList = new ArrayList<>(); + allDataList.addAll(blankList); + allDataList.addAll(excelRepeatList); + allDataList.addAll(noMatchList); + allDataList.addAll(noPermList); + allDataList.addAll(moreMatchList); + allDataList.addAll(readonlyList); + allDataList.addAll(matchShapeList); + // 整体按照Excel表中顺序排序 + allDataList.sort((a1, a2)-> {return a1.getExcelShapeModel().getRow() - a2.getExcelShapeModel().getRow();}); + + // 构造结果集返回给前端 + int totalCount = allDataList.size(); + int repeatCount = excelRepeatList.size(); + int blankCount = blankList.size(); + int noMatchCount = noMatchList.size(); + int noPermCount = noPermList.size(); + int moreMatchCount = moreMatchList.size(); + int readonlyCount = readonlyList.size(); + int okCount = 0; + int errCount = 0; + for (RepositoryShapeInfoModel model : matchShapeList) { + model.setRowOk(true); + JSONArray arr = model.getCheckResult(); + for (int i = 0; i < arr.size(); i++) { + if (!arr.getJSONObject(i).getBooleanValue("isOk")) { + model.setRowOk(false); + } + } + if (model.isRowOk()) { + okCount++; + } else { + errCount++; + } + } + // 构造返回前端数据 + JSONArray result = new JSONArray(); + for (int i = 0; i < allDataList.size(); i++) { + RepositoryShapeInfoModel model = allDataList.get(i); + if ("blank".equals(model.getResult()) || + "repeat".equals(model.getResult()) || + "noMatch".equals(model.getResult()) || + "noPerm".equals(model.getResult()) || + "moreMatch".equals(model.getResult()) || + "readonly".equals(model.getResult())) { + JSONArray row = new JSONArray(); + List list = model.getExcelShapeModel().getRowData(); + for (int j = 0; j < list.size(); j++) { + String s = list.get(j); + JSONObject cell = new JSONObject(); + cell.put("name", titleList.get(j)); + cell.put("name2", ShapeConst.EXTEND_PROP_PREFIX + titleList.get(j) + ShapeConst.EXTEND_PROP_SUFFIX); + if (ShapeConst.TABLE_REPOSITORY_NAME.equals(titleList.get(j))) { + cell.put("isOk", false); + cell.put("msg", model.getRowMsg()); + } else { + cell.put("isOk", true); + cell.put("msg", ""); + } + cell.put("value", s); + row.add(cell); + } + JSONObject rowResult = new JSONObject(); + rowResult.put("row", row); + rowResult.put("excelNo", model.getExcelShapeModel().getRow());// Excel中行 + rowResult.put("isRowOk", model.isRowOk()); + rowResult.put("result", model.getResult()); + result.add(rowResult); + } else if ("add".equals(model.getResult()) || "update".equals(model.getResult())) { + JSONArray row = model.getCheckResult(); + JSONObject rowResult = new JSONObject(); + rowResult.put("row", row); + rowResult.put("excelNo", model.getExcelShapeModel().getRow());// Excel中行 + rowResult.put("isRowOk", model.isRowOk()); + rowResult.put("result", model.getResult()); + rowResult.put("repositoryId", model.getRepositoryId()); + rowResult.put("shapeId", model.getShapeId()); + result.add(rowResult); + } + } + JSONObject ro = new JSONObject(); + ro.put("result", result); + ro.put("totalCount", totalCount); + ro.put("repeatCount", repeatCount); + ro.put("blankCount", blankCount); + ro.put("noPermCount", noPermCount); + ro.put("moreMatchCount", moreMatchCount); + ro.put("readonlyCount", readonlyCount); + ro.put("noMatchCount", noMatchCount); + ro.put("okCount", okCount); + ro.put("errCount", errCount); + return ro; + } + + /** * 获取更多特性 * @param methodId @@ -765,4 +1430,88 @@ public class ValidShapeExcel { } return ResponseObject.newOkResponse(); } + + /** + * 校验标题行 + * @param titleRow + */ + public ResponseObject checkTitleRowImport(String wsId, List titleRow, String methodCategory) { + // 标题固定行验证 + if (titleRow.size() < ShapeConst.SHAPE_TITLE_ROW_IMPORT.length) {// 固定行列不够 + StringBuilder msg = new StringBuilder(); + msg.append("固定属性标题要求:").append(ShapeConst.SHAPE_BASE_TITLE_ROW_IMPORT).append("

"); + msg.append("请按照以上固定属性内容及顺序调整工作表并重新上传Excel文件"); + msg.insert(0, errMsg); + return ResponseObject.newErrResponse(msg.toString()); + } + // 校验固定属性是否符合要求 + List illegalBaseTitle = new ArrayList<>(); + for (int i = 0; i < titleRow.size(); i++) { + if (i < ShapeConst.SHAPE_TITLE_ROW_IMPORT.length) { + if (!ShapeConst.SHAPE_TITLE_ROW_IMPORT[i].equals(titleRow.get(i))) { + illegalBaseTitle.add(titleRow.get(i)); + } + } + } + if (illegalBaseTitle.size() > 0) { + StringBuilder msg = new StringBuilder(); + msg.append("固定属性标题要求:").append(ShapeConst.SHAPE_BASE_TITLE_ROW_IMPORT).append("

"); + msg.append("不符合要求的属性标题范围:" + String.join("、", illegalBaseTitle)).append("

"); + msg.append("请按照以上固定属性内容及顺序调整工作表并重新上传Excel文件"); + msg.insert(0, errMsg); + return ResponseObject.newErrResponse(msg.toString()); + } + // 扩展属性验证 + if (titleRow.size() > ShapeConst.SHAPE_TITLE_ROW_IMPORT.length) {// 有扩展属性 + List illegalAttrTitle = new ArrayList<>(); + // 获取当前扩展属性 + Set attributeNames = ShapeUtil.getShapeMethodAttrNames(wsId, methodCategory); + for (int i = ShapeConst.SHAPE_TITLE_ROW_IMPORT.length; i < titleRow.size(); i++) { + String title = titleRow.get(i); + int prefix = title.indexOf("扩展<"); + int suffix = title.lastIndexOf(">"); + if (prefix == -1 || suffix == -1 || prefix > suffix || suffix != title.length() -1) { + illegalAttrTitle.add(title); + continue; + } + String propertyName = title.substring(prefix + 3, suffix); + if (!attributeNames.contains(propertyName)) { + illegalAttrTitle.add(title.replace("<", "<").replace(">", ">")); + } + } + if (illegalAttrTitle.size() > 0) { + List list = new ArrayList(attributeNames); + list.sort((name1, name2) -> name1.compareTo(name2)); + StringBuilder msg = new StringBuilder(); + msg.append("扩展属性要求格式:扩展<xxx>").append("

"); + msg.append("标准扩展属性范围:" + String.join("、", list)).append("

"); + msg.append("不符合要求的属性标题范围:" + String.join("、", illegalAttrTitle)).append("

"); + msg.append("请按照以上格式及标准扩展属性范围调整工作表并重新上传Excel文件"); + msg.insert(0, errMsg); + return ResponseObject.newErrResponse(msg.toString()); + } + // 校验是否有重复标题,前面几列固定不校验,只在扩展属性校验 + List repeatTitle = new ArrayList<>(); + Set set = new HashSet<>(); + for (int i = ShapeConst.SHAPE_TITLE_ROW_IMPORT.length; i < titleRow.size(); i++) { + String title = titleRow.get(i); + if (!UtilString.isEmpty(title)) { + if (set.contains(title)) { + repeatTitle.add(title); + } else { + set.add(title); + } + } + } + if (repeatTitle.size() > 0) { + StringBuilder msg = new StringBuilder(); + msg.append("属性重复").append("

"); + msg.append("重复的属性标题:" + String.join("、", repeatTitle)).append("

"); + msg.append("请调整重复的属性并重新上传Excel文件"); + msg.insert(0, errMsg); + return ResponseObject.newErrResponse(msg.toString()); + } + } + return ResponseObject.newOkResponse(); + } } diff --git a/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/model/CellObject.java b/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/model/CellObject.java new file mode 100644 index 00000000..d22ea4f2 --- /dev/null +++ b/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/model/CellObject.java @@ -0,0 +1,108 @@ +package com.actionsoft.apps.coe.pal.batch.web.create.shape.model; + + +import com.alibaba.fastjson.JSONArray; + +/** + * 前后入参table解析后cell对象 + */ +public class CellObject { + + /** + * 模型名称 + */ + private String modelName; + /** + * 模型类型 + */ + private String modelType; + /** + * 形状名称 + */ + private String shapeName; + /** + * 形状类型 + */ + private String shapeType; + /** + * 形状分支 + */ + private String shapeBranch; + /** + * 形状序号 + */ + private String shapeNum; + /** + * 拓展属性数组 + */ + private JSONArray expandArr; + + public CellObject() { + } + + public CellObject(String modelName, String modelType, String shapeName, String shapeType, String shapeBranch, String shapeNum, JSONArray expandArr) { + this.modelName = modelName; + this.modelType = modelType; + this.shapeName = shapeName; + this.shapeType = shapeType; + this.shapeBranch = shapeBranch; + this.shapeNum = shapeNum; + this.expandArr = expandArr; + } + + public String getModelName() { + return modelName; + } + + public void setModelName(String modelName) { + this.modelName = modelName; + } + + public String getModelType() { + return modelType; + } + + public void setModelType(String modelType) { + this.modelType = modelType; + } + + public String getShapeName() { + return shapeName; + } + + public void setShapeName(String shapeName) { + this.shapeName = shapeName; + } + + public String getShapeType() { + return shapeType; + } + + public void setShapeType(String shapeType) { + this.shapeType = shapeType; + } + + public String getShapeBranch() { + return shapeBranch; + } + + public void setShapeBranch(String shapeBranch) { + this.shapeBranch = shapeBranch; + } + + public String getShapeNum() { + return shapeNum; + } + + public void setShapeNum(String shapeNum) { + this.shapeNum = shapeNum; + } + + public JSONArray getExpandArr() { + return expandArr; + } + + public void setExpandArr(JSONArray expandArr) { + this.expandArr = expandArr; + } +} diff --git a/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/model/ExcelShapeModel.java b/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/model/ExcelShapeModel.java index 0b377239..01567677 100644 --- a/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/model/ExcelShapeModel.java +++ b/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/model/ExcelShapeModel.java @@ -11,6 +11,10 @@ public class ExcelShapeModel { private String repositoryType; private String shapeName; private String shapeType; + //导入---形状分支 + private String shapeBranch; + //导入 --- 形状编号 + private String shapeNo; private List rowData;// 扩展属性内容 public int getRow() { @@ -60,4 +64,20 @@ public class ExcelShapeModel { public void setRepositoryType(String repositoryType) { this.repositoryType = repositoryType; } + + public String getShapeBranch() { + return shapeBranch; + } + + public void setShapeBranch(String shapeBranch) { + this.shapeBranch = shapeBranch; + } + + public String getShapeNo() { + return shapeNo; + } + + public void setShapeNo(String shapeNo) { + this.shapeNo = shapeNo; + } } diff --git a/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/model/RepositoryShapeInfoModel.java b/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/model/RepositoryShapeInfoModel.java index 8cb634fa..e12ed968 100644 --- a/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/model/RepositoryShapeInfoModel.java +++ b/com.actionsoft.apps.coe.pal.batch/src/com/actionsoft/apps/coe/pal/batch/web/create/shape/model/RepositoryShapeInfoModel.java @@ -16,6 +16,8 @@ public class RepositoryShapeInfoModel { private String shapeName;// 形状名称 private String shapeMethodId;// 形状所属建模方法类型 private String shapeType;// 形状类型 + private String shapeBranch;// 导入---形状分支 + private String shapeNo;// 导入--- 形状吧编号 private boolean isPalShape;// 是否pal存在的形状,用户判断是否需要新增形状还是更新形状 @@ -140,4 +142,20 @@ public class RepositoryShapeInfoModel { public void setShapeType(String shapeType) { this.shapeType = shapeType; } + + public String getShapeBranch() { + return shapeBranch; + } + + public void setShapeBranch(String shapeBranch) { + this.shapeBranch = shapeBranch; + } + + public String getShapeNo() { + return shapeNo; + } + + public void setShapeNo(String shapeNo) { + this.shapeNo = shapeNo; + } }