Bladeren bron

完善物理世界基础表的校验逻辑

cuixubin 4 jaren geleden
bovenliggende
commit
110066a4e4

+ 1 - 1
pom.xml

@@ -79,7 +79,7 @@
     </repositories>
 
     <build>
-        <finalName>file-move-tool</finalName>
+        <finalName>data-platform-tool</finalName>
         <resources>
             <resource>
                 <directory>src/main/java</directory>

+ 13 - 1
src/main/java/com/persagy/dptool/CommonUtil.java

@@ -232,7 +232,19 @@ public class CommonUtil {
                         }
 
                         if(fieldCheck.existGraphId() && physicalObject.graphIdSet != null && !physicalObject.graphIdSet.contains(value)) {
-                            errorMsg += fieldName + "值在objects表中不存在。";
+                            errorMsg += fieldName + "值在graph_instance表中不存在。";
+                        }
+
+                        if(fieldCheck.existInfoCodeSchemeId() && physicalObject.infoCodeSchemeIdSet != null && !physicalObject.infoCodeSchemeIdSet.contains(value)) {
+                            errorMsg += fieldName + "值在infocode_scheme表中不存在。";
+                        }
+
+                        if(fieldCheck.existCtmDictId() && physicalObject.ctmDicIdSet != null && !physicalObject.ctmDicIdSet.contains(value)) {
+                            errorMsg += fieldName + "值在ctm_dict表中不存在。";
+                        }
+
+                        if(fieldCheck.existCtmDictNodeType() && !ConstantData.customDictNodeType.contains(value)) {
+                            errorMsg += fieldName + "值不合法!取值仅限于以下:" + ConstantData.customDictNodeType;
                         }
 
                         if(errorMsg.length() > 0) {

+ 2 - 0
src/main/java/com/persagy/dptool/ConstantData.java

@@ -30,6 +30,8 @@ public class ConstantData {
     public static final String tablesFileType = ".json";
     /** 物理世界数据表名称集合 */
     public static List<String> tablesNameList = new ArrayList<>(Arrays.asList(physicalWorldTablesName.split(",")));
+    /** 自定义字典方案节点类型 */
+    public static Set<String> customDictNodeType = new HashSet<>(Arrays.asList("family", "eq"));
 
     static {
         imgKeyMap.put("dev", "123"); imgKeyMap.put("saas", "46f869eea8b31d14");

+ 1 - 0
src/main/java/com/persagy/dptool/MainApp.java

@@ -21,6 +21,7 @@ public class MainApp extends Application {
         Parent root = new FXMLLoader().load(is);
         primaryStage.setTitle("data-platform-tool");
         primaryStage.setScene(new Scene(root));
+        primaryStage.setResizable(false);
         primaryStage.show();
     }
 }

+ 280 - 5
src/main/java/com/persagy/dptool/PhysicalCheckUtil.java

@@ -2,12 +2,10 @@ package com.persagy.dptool;
 
 import com.persagy.dptool.dto.PhysicalObject;
 import com.persagy.dptool.dto.physical.*;
+import com.persagy.dptool.dto.physical.Objects;
 
 import java.io.File;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 
 public class PhysicalCheckUtil {
     public static final String[] tipsArray = {"无异常。", "无指定项目数据。", "无数据。"};
@@ -166,13 +164,25 @@ public class PhysicalCheckUtil {
             return tipsArray[2];
         }
 
+        StringBuilder noObjErr = new StringBuilder();
+        Set<String> graphIdSet = new HashSet<>();
         List<RelBtwGraphPeriod> relBtwGraphPeriods = new ArrayList<>();
         try {
+            String graphType = null, sequenceId = null;
             for(String jsonStr : dataList) {
                 if(jsonStr != null && jsonStr.length() > 2) {
                     RelBtwGraphPeriod item = CommonUtil.jsonStrToObj(jsonStr, RelBtwGraphPeriod.class);
                     if(physicalObject.pjId.equals(item.getProject_id())) {
                         relBtwGraphPeriods.add(item);
+
+                        graphType = item.getGraph_type();
+                        sequenceId = item.getSequence_id();
+                        if(null != graphType && sequenceId != null) {
+                            graphIdSet.add(graphType+sequenceId);
+                            if(physicalObject.graphIdSet != null && !physicalObject.graphIdSet.contains(graphType+sequenceId)) {
+                                noObjErr.append(item.toString() + "记录异常!graph_instance表无对应记录。\n");
+                            }
+                        }
                     }
                 }
             }
@@ -185,9 +195,17 @@ public class PhysicalCheckUtil {
             return tipsArray[1];
         }
 
+        if(!graphIdSet.isEmpty()) {
+            physicalObject.graphIdPeriodSet = new HashSet<>(graphIdSet);
+        }
+
         String errorMsg = CommonUtil.annotationFieldCheck(relBtwGraphPeriods, physicalObject);
         if(null != errorMsg) {
-            return  errorMsg;
+            noObjErr.append(errorMsg);
+        }
+
+        if(noObjErr.length() > 0) {
+            return noObjErr.toString();
         }
 
         return tipsArray[0];
@@ -297,4 +315,261 @@ public class PhysicalCheckUtil {
 
         return tipsArray[0];
     }
+
+    public String check_infocode_scheme_detail(File file, PhysicalObject physicalObject) {
+        List<String> dataList = CommonUtil.readFileToList(file);
+        if(dataList.isEmpty()) {
+            return tipsArray[2];
+        }
+
+        List<InfocodeSchemeDetail> infocodeSchemeDetails = new ArrayList<>();
+        try {
+            for(String jsonStr : dataList) {
+                if(jsonStr != null && jsonStr.length() > 2) {
+                    InfocodeSchemeDetail item = CommonUtil.jsonStrToObj(jsonStr, InfocodeSchemeDetail.class);
+                    if(physicalObject.infoCodeSchemeIdSet != null && physicalObject.infoCodeSchemeIdSet.contains(item.getScheme_id())) {
+                        infocodeSchemeDetails.add(item);
+                    }
+                }
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+            return "数据格式错误!无法转为Json对象。";
+        }
+
+        if(infocodeSchemeDetails.isEmpty()) {
+            return tipsArray[2];
+        }
+
+        String errorMsg = CommonUtil.annotationFieldCheck(infocodeSchemeDetails, physicalObject);
+        if(null != errorMsg) {
+            return  errorMsg;
+        }
+
+        return tipsArray[0];
+    }
+
+    public String check_ctm_dict(File file, PhysicalObject physicalObject) {
+        List<String> dataList = CommonUtil.readFileToList(file);
+        if(dataList.isEmpty()) {
+            return tipsArray[2];
+        }
+
+        List<CtmDict> ctmDicts = new ArrayList<>();
+        Set<String> ctmDicIdSet = new HashSet<>();
+        try {
+            for(String jsonStr : dataList) {
+                if(jsonStr != null && jsonStr.length() > 2) {
+                    CtmDict item = CommonUtil.jsonStrToObj(jsonStr, CtmDict.class);
+                    if(item.getId() != null) {
+                        ctmDicIdSet.add(item.getId());
+                    }
+                    ctmDicts.add(item);
+                }
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+            return "数据格式错误!无法转为Json对象。";
+        }
+
+        if(ctmDicts.isEmpty()) {
+            return tipsArray[2];
+        }
+
+        if(!ctmDicIdSet.isEmpty()) {
+            physicalObject.ctmDicIdSet = new HashSet<>(ctmDicIdSet);
+        }
+
+        String errorMsg = CommonUtil.annotationFieldCheck(ctmDicts, physicalObject);
+        if(null != errorMsg) {
+            return  errorMsg;
+        }
+
+        return tipsArray[0];
+    }
+
+    public String check_ctm_dict_follower(File file, PhysicalObject physicalObject) {
+        List<String> dataList = CommonUtil.readFileToList(file);
+        if(dataList.isEmpty()) {
+            return tipsArray[2];
+        }
+
+        List<CtmDictFollower> ctmDictFollowers = new ArrayList<>();
+        try {
+            for(String jsonStr : dataList) {
+                if(jsonStr != null && jsonStr.length() > 2) {
+                    CtmDictFollower item = CommonUtil.jsonStrToObj(jsonStr, CtmDictFollower.class);
+                    if(physicalObject.pjId.equals(item.getProject_id())) {
+                        ctmDictFollowers.add(item);
+                    }
+                }
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+            return "数据格式错误!无法转为Json对象。";
+        }
+
+        if(ctmDictFollowers.isEmpty()) {
+            return tipsArray[1];
+        }
+
+        String errorMsg = CommonUtil.annotationFieldCheck(ctmDictFollowers, physicalObject);
+        if(null != errorMsg) {
+            return  errorMsg;
+        }
+
+        return tipsArray[0];
+    }
+
+    public String check_ctm_node(File file, PhysicalObject physicalObject) {
+        List<String> dataList = CommonUtil.readFileToList(file);
+        if(dataList.isEmpty()) {
+            return tipsArray[2];
+        }
+
+        List<CtmNode> ctmNodes = new ArrayList<>();
+        // 字典id:该字典下的所有ctmNode
+        Map<String, List<CtmNode>> dicId2Nodes = new HashMap<>();
+        // 字典id:该字典下的所有专业编码
+        Map<String, Set<String>> dicId2MajorCode = new HashMap<>();
+        // 字典id:该字典下的所有系统编码
+        Map<String, Set<String>> dicId2SystemCode = new HashMap<>();
+        // 字典id:该字典下的所有设备编码
+        Map<String, Set<String>> dicId2EquipCode = new HashMap<>();
+        // 字典id:该字典下的所有部件编码
+        Map<String, Set<String>> dicId2CompCode = new HashMap<>();
+
+        StringBuilder eqTreeErr = new StringBuilder();
+
+        try {
+            for(String jsonStr : dataList) {
+                if(jsonStr != null && jsonStr.length() > 2) {
+                    CtmNode item = CommonUtil.jsonStrToObj(jsonStr, CtmNode.class);
+                    ctmNodes.add(item);
+
+                    // 对设备岗位数相关数据进行处理
+                    String dictId = item.getDict_id();
+                    if(dictId != null && "eq".equals(item.getType())) {
+                        if(dicId2Nodes.containsKey(dictId)) {
+                            dicId2Nodes.get(dictId).add(item);
+                        }else {
+                            dicId2Nodes.put(dictId, new ArrayList<>(Arrays.asList(item)));
+                        }
+
+                        String code = item.getCode();
+                        if(code != null) {
+                            Set<String> majorSet = dicId2MajorCode.get(dictId);
+                            if(null == majorSet) {
+                                majorSet = new HashSet<>();
+                                dicId2MajorCode.put(dictId, majorSet);
+                            }
+
+                            Set<String> systemSet = dicId2SystemCode.get(dictId);
+                            if(null == systemSet) {
+                                systemSet = new HashSet<>();
+                                dicId2SystemCode.put(dictId, systemSet);
+                            }
+
+                            Set<String> equipSet = dicId2EquipCode.get(dictId);
+                            if(null == equipSet) {
+                                equipSet = new HashSet<>();
+                                dicId2EquipCode.put(dictId, equipSet);
+                            }
+
+                            Set<String> compSet = dicId2CompCode.get(dictId);
+                            if(null == compSet) {
+                                compSet = new HashSet<>();
+                                dicId2CompCode.put(dictId, compSet);
+                            }
+
+                            if(code.length() == 2) {
+                                if(item.getParent() == null) {
+                                    // 专业码
+                                    if(majorSet.contains(code)) {
+                                        eqTreeErr.append(item.toString() + "记录异常!code值重复。\n");
+                                    }else {
+                                        majorSet.add(code);
+                                    }
+                                }else {
+                                    // 系统码
+                                    if(systemSet.contains(code)) {
+                                        eqTreeErr.append(item.toString() + "记录异常!code值重复。\n");
+                                    }else {
+                                        systemSet.add(code);
+                                    }
+                                }
+                            }else if(code.length() == 4) {
+                                // 设备码
+                                if(equipSet.contains(code)) {
+                                    eqTreeErr.append(item.toString() + "记录异常!code值重复。\n");
+                                }else {
+                                    equipSet.add(code);
+                                }
+                            }else {
+                                // 其他类型
+                                if(compSet.contains(code)) {
+                                    eqTreeErr.append(item.toString() + "记录异常!code值重复。\n");
+                                }else {
+                                    compSet.add(code);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+            return "数据格式错误!无法转为Json对象。";
+        }
+
+        if(ctmNodes.isEmpty()) {
+            return tipsArray[2];
+        }
+
+        // 进行设备编码校验,编码长度,编码去重,父级编码存在性校验
+        if(!dicId2Nodes.isEmpty()) {
+            String code = "";
+            String parent = "";
+            int codeLength = -1;
+            for(String dicId : dicId2Nodes.keySet()) {
+                for(CtmNode node : dicId2Nodes.get(dicId)) {
+                    code = node.getCode();
+                    if(null == code) {
+                        continue;
+                    }
+
+                    parent = node.getParent();
+                    codeLength = code.length();
+
+                    if(codeLength == 2 ) {
+                        if(parent != null && !dicId2MajorCode.get(dicId).contains(parent)) {
+                            eqTreeErr.append(node.toString() + "记录异常!找不到parent值对应的记录。\n");
+                        }
+                    }else if(codeLength == 4) {
+                        if(!dicId2SystemCode.get(dicId).contains(parent)) {
+                            eqTreeErr.append(node.toString() + "记录异常!parent值不能为null且对应记录必须存在。\n");
+                        }
+                    }else if(codeLength == 6) {
+                        if(!dicId2EquipCode.get(dicId).contains(parent)) {
+                            eqTreeErr.append(node.toString() + "记录异常!parent值不能为null且对应记录必须存在。\n");
+                        }
+                    }else {
+                        eqTreeErr.append(node.toString() + "记录异常!code值长度不合法。专业和系统长度为2,设备长度为4,部件长度为6。\n");
+                    }
+                }
+            }
+        }
+
+        String errorMsg = CommonUtil.annotationFieldCheck(ctmNodes, physicalObject);
+        if(null != errorMsg) {
+            eqTreeErr.append(errorMsg);
+        }
+
+        if(eqTreeErr.length() > 0) {
+            return eqTreeErr.toString();
+        }
+
+        return tipsArray[0];
+    }
+
 }

+ 57 - 2
src/main/java/com/persagy/dptool/PrimaryController.java

@@ -8,9 +8,11 @@ import javafx.fxml.Initializable;
 import javafx.scene.control.*;
 import javafx.scene.layout.BorderPane;
 import javafx.stage.DirectoryChooser;
+import javafx.stage.FileChooser;
 
 import java.io.File;
 import java.net.URL;
+import java.util.Date;
 import java.util.ResourceBundle;
 
 public class PrimaryController implements Initializable {
@@ -28,6 +30,8 @@ public class PrimaryController implements Initializable {
     @FXML
     public TextField txfProject;
     @FXML
+    public TextField txfCheckResultFile;
+    @FXML
     public Button btnSelectDirJson;
     @FXML
     public Button btnCheck;
@@ -44,6 +48,7 @@ public class PrimaryController implements Initializable {
     @FXML
     public Label lblState;
 
+    private static File tableCheckResultFile;
 
     @Override
     public void initialize(URL location, ResourceBundle resources) {
@@ -56,6 +61,13 @@ public class PrimaryController implements Initializable {
             tableNameSBStr.append("  " + (i+1) + ". " + ConstantData.tablesNameList.get(i) + "\n");
         }
         txaContentJson.setText("目前只能校验HBase数据库中,物理世界的以下数据表数据:\n" + tableNameSBStr);
+
+        String checkResultFileName = "checkResult" + new Date().getTime() + ".txt";
+        txfCheckResultFile.setText(PrimaryController.class.getClassLoader().getResource("").toString() + checkResultFileName);
+
+        // ----
+        txfProject.setText("Pj3101040001");
+        txfDirJson.setText("D:\\var\\tableJson");
     }
 
     /**
@@ -63,7 +75,7 @@ public class PrimaryController implements Initializable {
      * @param e
      */
     public void selectDir(ActionEvent e) {
-        DirectoryChooser dirChooser =new DirectoryChooser();
+        DirectoryChooser dirChooser = new DirectoryChooser();
         dirChooser.setTitle("选择配置文件目录");
 
         File folder = dirChooser.showDialog(paneRoot.getScene().getWindow());
@@ -73,12 +85,25 @@ public class PrimaryController implements Initializable {
         }
     }
 
+    public void selectTxtFile(ActionEvent e) {
+        FileChooser fileChooser = new FileChooser();
+        fileChooser.setTitle("指定存放结果文件");
+
+        fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("Text", "*.txt"));
+
+        File file = fileChooser.showSaveDialog(paneRoot.getScene().getWindow());
+
+        if(null != file) {
+            txfCheckResultFile.setText(file.getAbsolutePath());
+        }
+    }
+
     /**
      * 选择配置文件目录
      * @param e
      */
     public void selectDirJson(ActionEvent e) {
-        DirectoryChooser dirChooser =new DirectoryChooser();
+        DirectoryChooser dirChooser = new DirectoryChooser();
         dirChooser.setTitle("选择json文件目录");
 
         File folder = dirChooser.showDialog(paneRoot.getScene().getWindow());
@@ -110,6 +135,7 @@ public class PrimaryController implements Initializable {
      * @param e
      */
     public void checkJsonFile(ActionEvent e) {
+        txaContentJson.setText("");
         String projectId = txfProject.getText();
         PhysicalObject physicalObject = null;
         if(projectId != null && projectId.trim().length() == 12 && projectId.startsWith("Pj")) {
@@ -120,6 +146,35 @@ public class PrimaryController implements Initializable {
             return;
         }
 
+        String logFilePath = txfCheckResultFile.getText();
+        if(logFilePath == null || logFilePath.trim().length() < 0) {
+            txaContentJson.setText("请先指定存放结果文件!");
+            txfCheckResultFile.requestFocus();
+            return;
+        }
+        File logFile = new File(logFilePath);
+        try {
+            if(!logFile.exists()) {
+                logFile.createNewFile();
+            }
+
+            if(!logFile.exists() || !logFile.isFile()) {
+                txaContentJson.setText("存放结果文件无法访问,请重新指定或手动创建!");
+                txfCheckResultFile.requestFocus();
+                return;
+            }
+        }catch (Exception ex) {
+            logFile = null;
+        }
+
+        if(logFile == null) {
+            txaContentJson.setText("存放结果文件不存在,请手动创建并指定!");
+            txfCheckResultFile.requestFocus();
+            return;
+        }else {
+            tableCheckResultFile = logFile;
+        }
+
         File jsonFileDir = null;
         String filePath = txfDirJson.getText();
 

+ 34 - 0
src/main/java/com/persagy/dptool/TaskFactory.java

@@ -110,6 +110,11 @@ public class TaskFactory {
                     checkResult.append(subCheckResult);
                 }
 
+                String relationCheckResult = relationCheck(physicalObject);
+                if(null != relationCheckResult) {
+                    checkResult.append(relationCheckResult);
+                }
+
                 Platform.runLater(()->{
                     controller.setDisable(false, 2);
                     controller.piState.setVisible(false);
@@ -122,6 +127,35 @@ public class TaskFactory {
     }
 
     /**
+     * 跨表查询校验
+     * @param physicalObject
+     * @return 异常信息,返回null表示无异常
+     */
+    private static String relationCheck(PhysicalObject physicalObject) {
+        StringBuilder sbStr = new StringBuilder("跨表数据异常:\n");
+        if(physicalObject.graphIdSet != null && physicalObject.graphIdPeriodSet != null) {
+            Set<String> errorGraphIdSet = new HashSet<>();
+            for(String graphId : physicalObject.graphIdSet) {
+                if(!physicalObject.graphIdPeriodSet.contains(graphId)) {
+                    errorGraphIdSet.add(graphId);
+                }
+            }
+
+            if(!errorGraphIdSet.isEmpty()) {
+                sbStr.append("[graph_instance, rel_btw_graph_period]表\n");
+                sbStr.append("graph_instance表中 ‘graphy_type字段值+sequence_id值’ 在rel_btw_graph_period表中缺少对应记录。异常数据:" + errorGraphIdSet);
+                sbStr.append("\n\n");
+            }
+        }
+
+        if(sbStr.length() > 20) {
+            return sbStr.toString();
+        }
+
+        return null;
+    }
+
+    /**
      * 校验单个物理世界数据表json文件数据
      * @param tableName 数据表名称
      * @param file json文件实例

+ 4 - 0
src/main/java/com/persagy/dptool/annotation/FieldCheck.java

@@ -20,4 +20,8 @@ public @interface FieldCheck {
     public boolean existGraphId() default false;
     /** 自定义信息点方案id存在判断 */
     public boolean existInfoCodeSchemeId() default false;
+    /** 用戶自定义字典方案id存在判断 */
+    public boolean existCtmDictId() default false;
+    /** 用戶自定义字典节点类型存在判断 */
+    public boolean existCtmDictNodeType() default false;
 }

+ 5 - 1
src/main/java/com/persagy/dptool/dto/PhysicalObject.java

@@ -11,8 +11,12 @@ public class PhysicalObject {
     public Set<String> objIdSet;
     /** 图实例id集合,默认为null */
     public Set<String> graphIdSet;
-    /** 自定义信息单方案id集合 */
+    /** 存在period的图实例id集合,默认为null */
+    public Set<String> graphIdPeriodSet;
+    /** 自定义信息點方案id集合 */
     public Set<String> infoCodeSchemeIdSet;
+    /** 用户自定义字典方案id集合 */
+    public Set<String> ctmDicIdSet;
 
     public PhysicalObject(String projectId, String pjId) {
         this.projectId = projectId;

+ 44 - 0
src/main/java/com/persagy/dptool/dto/physical/CtmDict.java

@@ -0,0 +1,44 @@
+package com.persagy.dptool.dto.physical;
+
+import com.persagy.dptool.annotation.FieldCheck;
+
+public class CtmDict extends PhysicalWorld {
+    @FieldCheck(canBeNull = false)
+    private String id;
+    @FieldCheck(canBeNull = false)
+    private String name;
+    private String desc;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    public void setDesc(String desc) {
+        this.desc = desc;
+    }
+
+    @Override
+    public String toString() {
+        return "{" +
+                "id='" + id + '\'' +
+                ", name='" + name + '\'' +
+                "..." +
+                '}';
+    }
+}

+ 34 - 0
src/main/java/com/persagy/dptool/dto/physical/CtmDictFollower.java

@@ -0,0 +1,34 @@
+package com.persagy.dptool.dto.physical;
+
+import com.persagy.dptool.annotation.FieldCheck;
+
+public class CtmDictFollower extends PhysicalWorld {
+    @FieldCheck(canBeNull = false, length = 10)
+    private String project_id;
+    @FieldCheck(canBeNull = false, existCtmDictId = true)
+    private String dict_id;
+
+    public String getProject_id() {
+        return project_id;
+    }
+
+    public void setProject_id(String project_id) {
+        this.project_id = project_id;
+    }
+
+    public String getDict_id() {
+        return dict_id;
+    }
+
+    public void setDict_id(String dict_id) {
+        this.dict_id = dict_id;
+    }
+
+    @Override
+    public String toString() {
+        return "{" +
+                "project_id='" + project_id + '\'' +
+                ", dict_id='" + dict_id + '\'' +
+                '}';
+    }
+}

+ 84 - 0
src/main/java/com/persagy/dptool/dto/physical/CtmNode.java

@@ -0,0 +1,84 @@
+package com.persagy.dptool.dto.physical;
+
+import com.persagy.dptool.annotation.FieldCheck;
+
+public class CtmNode extends PhysicalWorld {
+    @FieldCheck(canBeNull = false, existCtmDictId = true)
+    private String dict_id;
+    @FieldCheck(canBeNull = false, existCtmDictNodeType = true)
+    private String type;
+    @FieldCheck(canBeNull = false)
+    private String code;
+    @FieldCheck(canBeNull = false)
+    private String name;
+    private String parent;
+    private String ref;
+    private String family;
+
+    public String getDict_id() {
+        return dict_id;
+    }
+
+    public void setDict_id(String dict_id) {
+        this.dict_id = dict_id;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getParent() {
+        return parent;
+    }
+
+    public void setParent(String parent) {
+        this.parent = parent;
+    }
+
+    public String getRef() {
+        return ref;
+    }
+
+    public void setRef(String ref) {
+        this.ref = ref;
+    }
+
+    public String getFamily() {
+        return family;
+    }
+
+    public void setFamily(String family) {
+        this.family = family;
+    }
+
+    @Override
+    public String toString() {
+        return "{" +
+                "dict_id='" + dict_id + '\'' +
+                ", type='" + type + '\'' +
+                ", code='" + code + '\'' +
+                ", name='" + name + '\'' +
+                "..." +
+                '}';
+    }
+}

+ 1 - 1
src/main/java/com/persagy/dptool/dto/physical/GraphInstance.java

@@ -7,7 +7,7 @@ public class GraphInstance extends PhysicalWorld {
     private String project_id;
     @FieldCheck(canBeNull = false)
     private String graph_type;
-    @FieldCheck(canBeNull = false)
+    @FieldCheck(canBeNull = false, length = 3)
     private String sequence_id;
     private String obj_type;
     private String obj_id;

+ 129 - 0
src/main/java/com/persagy/dptool/dto/physical/InfocodeSchemeDetail.java

@@ -0,0 +1,129 @@
+package com.persagy.dptool.dto.physical;
+
+import com.persagy.dptool.annotation.FieldCheck;
+
+public class InfocodeSchemeDetail extends PhysicalWorld {
+    @FieldCheck(canBeNull = false, existInfoCodeSchemeId = true)
+    private String scheme_id;
+    @FieldCheck(canBeNull = false)
+    private String obj_type;
+    @FieldCheck(canBeNull = false)
+    private String first_tag;
+    private String second_tag;
+    @FieldCheck(canBeNull = false)
+    private String info_point_code;
+    private String info_point_name;
+    private String unit;
+    private String data_type;
+    private String input_mode;
+    private String data_source;
+    private String note;
+    private String func_id;
+
+    public String getScheme_id() {
+        return scheme_id;
+    }
+
+    public void setScheme_id(String scheme_id) {
+        this.scheme_id = scheme_id;
+    }
+
+    public String getObj_type() {
+        return obj_type;
+    }
+
+    public void setObj_type(String obj_type) {
+        this.obj_type = obj_type;
+    }
+
+    public String getFirst_tag() {
+        return first_tag;
+    }
+
+    public void setFirst_tag(String first_tag) {
+        this.first_tag = first_tag;
+    }
+
+    public String getSecond_tag() {
+        return second_tag;
+    }
+
+    public void setSecond_tag(String second_tag) {
+        this.second_tag = second_tag;
+    }
+
+    public String getInfo_point_code() {
+        return info_point_code;
+    }
+
+    public void setInfo_point_code(String info_point_code) {
+        this.info_point_code = info_point_code;
+    }
+
+    public String getInfo_point_name() {
+        return info_point_name;
+    }
+
+    public void setInfo_point_name(String info_point_name) {
+        this.info_point_name = info_point_name;
+    }
+
+    public String getUnit() {
+        return unit;
+    }
+
+    public void setUnit(String unit) {
+        this.unit = unit;
+    }
+
+    public String getData_type() {
+        return data_type;
+    }
+
+    public void setData_type(String data_type) {
+        this.data_type = data_type;
+    }
+
+    public String getInput_mode() {
+        return input_mode;
+    }
+
+    public void setInput_mode(String input_mode) {
+        this.input_mode = input_mode;
+    }
+
+    public String getData_source() {
+        return data_source;
+    }
+
+    public void setData_source(String data_source) {
+        this.data_source = data_source;
+    }
+
+    public String getNote() {
+        return note;
+    }
+
+    public void setNote(String note) {
+        this.note = note;
+    }
+
+    public String getFunc_id() {
+        return func_id;
+    }
+
+    public void setFunc_id(String func_id) {
+        this.func_id = func_id;
+    }
+
+    @Override
+    public String toString() {
+        return "{" +
+                "scheme_id='" + scheme_id + '\'' +
+                ", obj_type='" + obj_type + '\'' +
+                ", first_tag='" + first_tag + '\'' +
+                ", info_point_code='" + info_point_code + '\'' +
+                "..." +
+                '}';
+    }
+}

+ 1 - 1
src/main/java/com/persagy/dptool/dto/physical/RelBtwGraphPeriod.java

@@ -7,7 +7,7 @@ public class RelBtwGraphPeriod extends PhysicalWorld {
     private String project_id;
     @FieldCheck(canBeNull = false)
     private String graph_type;
-    @FieldCheck(canBeNull = false)
+    @FieldCheck(canBeNull = false, length = 3)
     private String sequence_id;
     @FieldCheck(canBeNull = false, length = 14)
     private String begin_time;

+ 17 - 14
src/main/java/com/persagy/dptool/primary.fxml

@@ -9,7 +9,7 @@
 <?import javafx.scene.control.*?>
 <?import javafx.scene.layout.*?>
 
-<BorderPane fx:id="paneRoot" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="640.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.persagy.dptool.PrimaryController">
+<BorderPane fx:id="paneRoot" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="640.0" prefWidth="860.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.persagy.dptool.PrimaryController">
    <top>
       <MenuBar BorderPane.alignment="CENTER">
         <menus>
@@ -31,27 +31,27 @@
               <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
                      <children>
                         <Label layoutX="12.0" layoutY="14.0" prefHeight="26.0" prefWidth="128.0" text="数据平台配置目录:" />
-                        <TextField fx:id="txfDir" layoutX="138.0" layoutY="12.0" prefHeight="30.0" prefWidth="520.0" promptText="D:/develop/tomcat9/webapps/data-platform-3/WEB-INF/classes/" />
-                        <Button fx:id="btnSelectDir" layoutX="668.0" layoutY="12.0" mnemonicParsing="false" onAction="#selectDir" text="选择" />
-                        <Button fx:id="btnCheck" layoutX="736.0" layoutY="12.0" mnemonicParsing="false" onAction="#checkConfig" text="校验" />
+                        <TextField fx:id="txfDir" layoutX="138.0" layoutY="12.0" prefHeight="30.0" prefWidth="592.0" promptText="D:/develop/tomcat9/webapps/data-platform-3/WEB-INF/classes/" />
+                        <Button fx:id="btnSelectDir" layoutX="733.0" layoutY="12.0" mnemonicParsing="false" onAction="#selectDir" text="···" />
+                        <Button fx:id="btnCheck" layoutX="776.0" layoutY="12.0" mnemonicParsing="false" onAction="#checkConfig" text="校验" />
                         <Label layoutX="138.0" layoutY="49.0" prefHeight="20.0" prefWidth="644.0" text="注: 路径为数据平台配置文件config.properties所在目录" textFill="#7c7c7c">
                            <font>
                               <Font size="14.0" />
                            </font>
                         </Label>
-                        <StackPane layoutX="138.0" layoutY="98.0" prefHeight="437.0" prefWidth="611.0">
+                        <StackPane layoutX="79.0" layoutY="98.0" prefHeight="437.0" prefWidth="746.0">
                            <children>
                               <FlowPane orientation="VERTICAL" prefHeight="200.0" prefWidth="200.0" vgap="20.0">
                                  <opaqueInsets>
                                     <Insets bottom="3.0" left="3.0" right="3.0" top="3.0" />
                                  </opaqueInsets>
                                  <children>
-                                    <TextArea fx:id="txaContent" editable="false" prefHeight="436.0" prefWidth="611.0" wrapText="true" />
+                                    <TextArea fx:id="txaContent" editable="false" prefHeight="436.0" prefWidth="747.0" wrapText="true" />
                                  </children>
                               </FlowPane>
                            </children>
                         </StackPane>
-                        <Label layoutX="72.0" layoutY="96.0" prefHeight="20.0" prefWidth="66.0" text="校验结果:" />
+                        <Label layoutX="9.0" layoutY="96.0" prefHeight="20.0" prefWidth="70.0" text="校验结果:" />
                      </children>
                   </AnchorPane>
             </content>
@@ -61,26 +61,29 @@
               <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
                      <children>
                         <Label layoutX="9.0" layoutY="56.0" prefHeight="26.0" prefWidth="98.0" text="json文件目录:" textAlignment="RIGHT" />
-                        <TextField fx:id="txfDirJson" layoutX="107.0" layoutY="54.0" prefHeight="30.0" prefWidth="544.0" />
-                        <Button fx:id="btnSelecDirJson" layoutX="668.0" layoutY="54.0" mnemonicParsing="false" onAction="#selectDirJson" text="选择" />
-                        <Button fx:id="btnCheckJson" layoutX="736.0" layoutY="54.0" mnemonicParsing="false" onAction="#checkJsonFile" text="校验" />
+                        <TextField fx:id="txfDirJson" layoutX="107.0" layoutY="54.0" prefHeight="30.0" prefWidth="620.0" />
+                        <Button fx:id="btnSelecDirJson" layoutX="731.0" layoutY="54.0" mnemonicParsing="false" onAction="#selectDirJson" text="···" />
+                        <Button fx:id="btnCheckJson" layoutX="777.0" layoutY="54.0" mnemonicParsing="false" onAction="#checkJsonFile" text="校验" />
                         <Label layoutX="107.0" layoutY="84.0" prefHeight="27.0" prefWidth="666.0" text="注: 只识别由HbaseCat工具导出的json文件,只能校验物理世界相关数据表,json文件名应与表名一致。" textFill="#7c7c7c">
                            <font>
                               <Font size="14.0" />
                            </font>
                         </Label>
-                        <StackPane layoutX="107.0" layoutY="133.0" prefHeight="397.0" prefWidth="645.0">
+                        <StackPane layoutX="107.0" layoutY="133.0" prefHeight="349.0" prefWidth="720.0">
                            <children>
                               <FlowPane prefHeight="375.0" prefWidth="645.0">
                                  <children>
-                                    <TextArea fx:id="txaContentJson" editable="false" prefHeight="397.0" prefWidth="648.0" wrapText="true" />
+                                    <TextArea fx:id="txaContentJson" editable="false" prefHeight="401.0" prefWidth="720.0" wrapText="true" />
                                  </children>
                               </FlowPane>
                            </children>
                         </StackPane>
-                        <Label layoutX="39.0" layoutY="133.0" prefHeight="20.0" prefWidth="68.0" text="校验结果:" />
+                        <Label layoutX="9.0" layoutY="133.0" prefHeight="20.0" prefWidth="98.0" text="校验结果概况:" />
                         <Label layoutX="55.0" layoutY="14.0" prefHeight="20.0" prefWidth="53.0" text="项目id: " textAlignment="RIGHT" />
-                        <TextField fx:id="txfProject" layoutX="107.0" layoutY="9.0" prefHeight="30.0" prefWidth="164.0" promptText="Pj1101010001" />
+                        <TextField fx:id="txfProject" layoutX="107.0" layoutY="9.0" prefHeight="30.0" prefWidth="138.0" promptText="Pj1101010001" />
+                        <Label layoutX="266.0" layoutY="14.0" text="存放结果文件: " />
+                        <TextField fx:id="txfCheckResultFile" editable="false" layoutX="366.0" layoutY="9.0" prefHeight="30.0" prefWidth="426.0" />
+                        <Button layoutX="796.0" layoutY="9.0" mnemonicParsing="false" onAction="#selectTxtFile" text="···" />
                      </children></AnchorPane>
             </content>
           </Tab>

+ 117 - 0
src/main/resources/primary.fxml

@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.effect.*?>
+<?import javafx.scene.text.*?>
+<?import javafx.geometry.*?>
+<?import java.lang.*?>
+<?import java.util.*?>
+<?import javafx.scene.*?>
+<?import javafx.scene.control.*?>
+<?import javafx.scene.layout.*?>
+
+<BorderPane fx:id="paneRoot" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="640.0" prefWidth="860.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.persagy.dptool.PrimaryController">
+   <top>
+      <MenuBar BorderPane.alignment="CENTER">
+        <menus>
+          <Menu mnemonicParsing="false" text="Help">
+            <items>
+                  <MenuItem mnemonicParsing="false" text="Help" />
+                  <SeparatorMenuItem mnemonicParsing="false" />
+              <MenuItem mnemonicParsing="false" text="About" />
+            </items>
+          </Menu>
+        </menus>
+      </MenuBar>
+   </top>
+   <center>
+      <TabPane fx:id="paneTab" prefHeight="200.0" prefWidth="200.0" tabClosingPolicy="UNAVAILABLE" BorderPane.alignment="CENTER">
+        <tabs>
+          <Tab text="配置校验">
+            <content>
+              <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
+                     <children>
+                        <Label layoutX="12.0" layoutY="14.0" prefHeight="26.0" prefWidth="128.0" text="数据平台配置目录:" />
+                        <TextField fx:id="txfDir" layoutX="138.0" layoutY="12.0" prefHeight="30.0" prefWidth="592.0" promptText="D:/develop/tomcat9/webapps/data-platform-3/WEB-INF/classes/" />
+                        <Button fx:id="btnSelectDir" layoutX="733.0" layoutY="12.0" mnemonicParsing="false" onAction="#selectDir" text="···" />
+                        <Button fx:id="btnCheck" layoutX="776.0" layoutY="12.0" mnemonicParsing="false" onAction="#checkConfig" text="校验" />
+                        <Label layoutX="138.0" layoutY="49.0" prefHeight="20.0" prefWidth="644.0" text="注: 路径为数据平台配置文件config.properties所在目录" textFill="#7c7c7c">
+                           <font>
+                              <Font size="14.0" />
+                           </font>
+                        </Label>
+                        <StackPane layoutX="79.0" layoutY="98.0" prefHeight="437.0" prefWidth="746.0">
+                           <children>
+                              <FlowPane orientation="VERTICAL" prefHeight="200.0" prefWidth="200.0" vgap="20.0">
+                                 <opaqueInsets>
+                                    <Insets bottom="3.0" left="3.0" right="3.0" top="3.0" />
+                                 </opaqueInsets>
+                                 <children>
+                                    <TextArea fx:id="txaContent" editable="false" prefHeight="436.0" prefWidth="747.0" wrapText="true" />
+                                 </children>
+                              </FlowPane>
+                           </children>
+                        </StackPane>
+                        <Label layoutX="9.0" layoutY="96.0" prefHeight="20.0" prefWidth="70.0" text="校验结果:" />
+                     </children>
+                  </AnchorPane>
+            </content>
+          </Tab>
+          <Tab text="物理世界">
+            <content>
+              <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
+                     <children>
+                        <Label layoutX="9.0" layoutY="56.0" prefHeight="26.0" prefWidth="98.0" text="json文件目录:" textAlignment="RIGHT" />
+                        <TextField fx:id="txfDirJson" layoutX="107.0" layoutY="54.0" prefHeight="30.0" prefWidth="620.0" />
+                        <Button fx:id="btnSelecDirJson" layoutX="731.0" layoutY="54.0" mnemonicParsing="false" onAction="#selectDirJson" text="···" />
+                        <Button fx:id="btnCheckJson" layoutX="777.0" layoutY="54.0" mnemonicParsing="false" onAction="#checkJsonFile" text="校验" />
+                        <Label layoutX="107.0" layoutY="84.0" prefHeight="27.0" prefWidth="666.0" text="注: 只识别由HbaseCat工具导出的json文件,只能校验物理世界相关数据表,json文件名应与表名一致。" textFill="#7c7c7c">
+                           <font>
+                              <Font size="14.0" />
+                           </font>
+                        </Label>
+                        <StackPane layoutX="107.0" layoutY="133.0" prefHeight="349.0" prefWidth="720.0">
+                           <children>
+                              <FlowPane prefHeight="375.0" prefWidth="645.0">
+                                 <children>
+                                    <TextArea fx:id="txaContentJson" editable="false" prefHeight="401.0" prefWidth="720.0" wrapText="true" />
+                                 </children>
+                              </FlowPane>
+                           </children>
+                        </StackPane>
+                        <Label layoutX="9.0" layoutY="133.0" prefHeight="20.0" prefWidth="98.0" text="校验结果概况:" />
+                        <Label layoutX="55.0" layoutY="14.0" prefHeight="20.0" prefWidth="53.0" text="项目id: " textAlignment="RIGHT" />
+                        <TextField fx:id="txfProject" layoutX="107.0" layoutY="9.0" prefHeight="30.0" prefWidth="138.0" promptText="Pj1101010001" />
+                        <Label layoutX="266.0" layoutY="14.0" text="存放结果文件: " />
+                        <TextField fx:id="txfCheckResultFile" layoutX="366.0" layoutY="9.0" prefHeight="30.0" prefWidth="426.0" />
+                        <Button layoutX="796.0" layoutY="9.0" mnemonicParsing="false" text="···" />
+                     </children></AnchorPane>
+            </content>
+          </Tab>
+            <Tab text="其他">
+              <content>
+                <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
+              </content>
+            </Tab>
+        </tabs>
+      </TabPane>
+   </center>
+   <bottom>
+      <HBox prefHeight="35.0" prefWidth="800.0" BorderPane.alignment="CENTER">
+         <children>
+            <ProgressIndicator fx:id="piState" prefHeight="26.0" prefWidth="30.0" progress="0.0">
+               <cursor>
+                  <Cursor fx:constant="NONE" />
+               </cursor>
+            </ProgressIndicator>
+            <Label fx:id="lblState" prefHeight="35.0" prefWidth="762.0">
+               <HBox.margin>
+                  <Insets left="3.0" />
+               </HBox.margin>
+            </Label>
+         </children>
+         <BorderPane.margin>
+            <Insets left="5.0" />
+         </BorderPane.margin>
+      </HBox>
+   </bottom>
+</BorderPane>