package com.chenyang.nse.bussiness.tools.engine.mapplet;

import com.chenyang.nse.bussiness.config.PropertiesLoaderUtils;
import com.chenyang.nse.bussiness.tools.io.FileTool;
import com.chenyang.nse.bussiness.tools.serialize.SerializeTool;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class DesensitizationRulesXmlParse {
   public static String rulesXmlParsing(String rulesXmlName) {
      String reFlg = "0";

      try {
         String xmlFilePath = PropertiesLoaderUtils.loadAllProperties("config.properties").getProperty("xmlLocation");
         String javaFilePath = PropertiesLoaderUtils.loadAllProperties("config.properties").getProperty("dic_mapplet_java_file_path");
         File file = new File(xmlFilePath + rulesXmlName + ".xml");
         if (!file.exists()) {
            System.out.println(">>>>>>>脱敏规则XML文件不存在，无法生成JAVA序列化对象");
            reFlg = "1";
            return reFlg;
         } else {
            FileTool.createFolder(javaFilePath);
            SAXReader reader = new SAXReader();
            reader.setEntityResolver(new MyEntityResolver());
            Document doc = reader.read(file);
            Element root = doc.getRootElement();
            Element repositoryInfo = root.element("REPOSITORY");
            Element folderInfo = repositoryInfo.element("FOLDER");
            Element mapplet = folderInfo.element("MAPPLET");
            String mappletName = mapplet.attributeValue("NAME");
            List<Element> instanceList = mapplet.elements("INSTANCE");
            List<Element> connectorList = mapplet.elements("CONNECTOR");
            Map<String, Element> connectorFMap = new HashMap();
            Map<String, Element> connectorTMap = new HashMap();

            for(int i = 0; i < connectorList.size(); ++i) {
               Element connectorInfo = (Element)connectorList.get(i);
               connectorFMap.put(connectorInfo.attributeValue("FROMINSTANCE") + "#" + connectorInfo.attributeValue("FROMFIELD"), connectorInfo);
               connectorTMap.put(connectorInfo.attributeValue("TOINSTANCE") + "#" + connectorInfo.attributeValue("TOFIELD"), connectorInfo);
            }

            List<Element> transformationList = mapplet.elements("TRANSFORMATION");
            Map<String, Element> transformationMap = new HashMap();

            for(int i = 0; i < transformationList.size(); ++i) {
               Element transformationInfo = (Element)transformationList.get(i);
               transformationMap.put(transformationInfo.attributeValue("NAME"), transformationInfo);
            }

            List<TransformationInfo> transformationInfoList = new ArrayList();
            ConcurrentLinkedQueue<TransformationInfo> transformationInfoQueue = new ConcurrentLinkedQueue();
            Map<String, TransformationInfo> transformationInfoMap = new HashMap();

            for(int i = 0; i < transformationList.size(); ++i) {
               Element transformationInfo = (Element)transformationList.get(i);
               String name = transformationInfo.attributeValue("NAME");
               String type = transformationInfo.attributeValue("TYPE");
               if (!"Mapplet".equalsIgnoreCase(type)) {
                  TransformationInfo tfInfo = new TransformationInfo();
                  tfInfo.setName(name);
                  tfInfo.setType(type);
                  Map<String, PortInfo> portMap = new HashMap();
                  List<Element> transformfieldList = transformationInfo.elements("TRANSFORMFIELD");

                  for(int j = 0; j < transformfieldList.size(); ++j) {
                     Element tffInfo = (Element)transformfieldList.get(j);
                     PortInfo portInfo = new PortInfo();
                     String portName = tffInfo.attributeValue("NAME");
                     portInfo.setName(portName);
                     portInfo.setDatatype(tffInfo.attributeValue("DATATYPE"));
                     portInfo.setPorttype(tffInfo.attributeValue("PORTTYPE"));
                     portInfo.setPrecision(tffInfo.attributeValue("PRECISION"));
                     portInfo.setScale(tffInfo.attributeValue("SCALE"));
                     if ("Expression".equals(type)) {
                        portInfo.setExpression(tffInfo.attributeValue("EXPRESSION"));
                     }

                     String keyName = name + "#" + portName;
                     if (connectorFMap.containsKey(keyName)) {
                        Element connectorF = (Element)connectorFMap.get(keyName);
                        portInfo.setNextPort(connectorF.attributeValue("TOFIELD"));
                        portInfo.setNextTransformationName(connectorF.attributeValue("TOINSTANCE"));
                        portInfo.setNextTransformationType(connectorF.attributeValue("TOINSTANCETYPE"));
                     }

                     if (connectorTMap.containsKey(keyName)) {
                        Element connectorT = (Element)connectorTMap.get(keyName);
                        portInfo.setPrePort(connectorT.attributeValue("FROMFIELD"));
                        portInfo.setPreTransformationName(connectorT.attributeValue("FROMINSTANCE"));
                        portInfo.setPreTransformationType(connectorT.attributeValue("FROMINSTANCETYPE"));
                     }

                     portMap.put(portName, portInfo);
                  }

                  if ("Expression".equalsIgnoreCase(type)) {
                     Map<String, String> portExpressStrMap = new HashMap();
                     Map<String, String> outPortExpressStrMap = new HashMap();

                     for(Map.Entry<String, PortInfo> expPortEntry : portMap.entrySet()) {
                        PortInfo expPortInfo = (PortInfo)expPortEntry.getValue();
                        if ("OUTPUT".equalsIgnoreCase(expPortInfo.getPorttype())) {
                           outPortExpressStrMap.put(expPortInfo.getName(), expPortInfo.getExpression());
                        } else if ("INPUT".equalsIgnoreCase(expPortInfo.getPorttype())) {
                           outPortExpressStrMap.put(expPortInfo.getName(), expPortInfo.getName());
                        } else {
                           portExpressStrMap.put(expPortInfo.getName(), expPortInfo.getExpression());
                        }
                     }

                     for(Map.Entry<String, String> outPortExpressEntry : outPortExpressStrMap.entrySet()) {
                        String outPortName = (String)outPortExpressEntry.getKey();
                        String outPortExpressStr = (String)outPortExpressEntry.getValue();

                        for(Map.Entry<String, String> PortExpressEntry : portExpressStrMap.entrySet()) {
                           String portName = (String)PortExpressEntry.getKey();
                           String portExpressStr = (String)PortExpressEntry.getValue();
                           if (StringUtils.isNotBlank(portExpressStr)) {
                              outPortExpressStr = outPortExpressStr.replace(portName, portExpressStr);
                           }
                        }

                        if (portMap.containsKey(outPortName)) {
                           PortInfo outExpPortInfo = (PortInfo)portMap.get(outPortName);
                           outExpPortInfo.setExpression(outPortExpressStr);
                        }
                     }
                  } else if ("Custom Transformation".equalsIgnoreCase(type)) {
                     List<Element> metadataextensionList = transformationInfo.elements("METADATAEXTENSION");

                     for(int j = 0; j < metadataextensionList.size(); ++j) {
                        Element metadataextensionInfo = (Element)metadataextensionList.get(j);
                        String medatatype = metadataextensionInfo.attributeValue("DATATYPE");
                        if ("XML".equalsIgnoreCase(medatatype)) {
                           String dmoXml = metadataextensionInfo.attributeValue("VALUE");
                           readStringXml(dmoXml, portMap);
                        }
                     }
                  }

                  tfInfo.setPortMap(portMap);
                  transformationInfoQueue.offer(tfInfo);
                  transformationInfoMap.put(name, tfInfo);
                  transformationInfoList.add(tfInfo);
               }
            }

            MappletDesigner mappletDesigner = new MappletDesigner(mappletName, transformationInfoQueue, transformationInfoMap, transformationInfoList);
            SerializeTool.saveObject(mappletDesigner, javaFilePath, mappletName);

            try {
               MappletDesigner mappletDesignerSerialize = (MappletDesigner)SerializeTool.readObject(javaFilePath, mappletName);
               System.out.println(">>>>>>>" + mappletDesignerSerialize.getName());
            } catch (Exception e) {
               System.out.println("读取时异常：" + e.getMessage());
            }

            return reFlg;
         }
      } catch (Exception e) {
         reFlg = "1";
         e.printStackTrace();
         return reFlg;
      } finally {
         ;
      }
   }

   public static void readStringXml(String xml, Map<String, PortInfo> portMap) {
      Document doc = null;

      try {
         doc = DocumentHelper.parseText(xml);
         Element root = doc.getRootElement();
         Element codepageInfo = root.element("CODEPAGE");
         String id = codepageInfo.attributeValue("ID");
         Element portinfo = root.element("PORTINFO");
         List<Element> portList = portinfo.elements("PORT");
         if (null != portList && portList.size() > 0) {
            for(int i = 0; i < portList.size(); ++i) {
               Element port = (Element)portList.get(i);
               String portName = port.attributeValue("NAME");
               if (portMap.containsKey(portName)) {
                  PortInfo curInputPortInfo = (PortInfo)portMap.get(portName);
                  curInputPortInfo.getDatatype();
                  String dataType = port.attributeValue("DATA_TYPE");
                  String seed = port.attributeValue("SEED");
                  Integer seedInt = 0;
                  if (StringUtils.isNotBlank(seed)) {
                     seedInt = Integer.valueOf(seed);
                  }

                  curInputPortInfo.setSeed(seedInt);
                  String maskingOption = port.attributeValue("MASKING_OPTION");
                  curInputPortInfo.setMaskingOption(maskingOption);
                  if (!"Substitution".equalsIgnoreCase(maskingOption) && !"置换".equalsIgnoreCase(maskingOption)) {
                     if (!"Random".equalsIgnoreCase(maskingOption) && !"随机".equalsIgnoreCase(maskingOption)) {
                        if (!"Key".equalsIgnoreCase(maskingOption) && !"键".equalsIgnoreCase(maskingOption)) {
                           if (!"Email address".equalsIgnoreCase(maskingOption) && !"电子邮件地址".equalsIgnoreCase(maskingOption) && !"Credit card".equalsIgnoreCase(maskingOption) && !"信用卡".equalsIgnoreCase(maskingOption) && !"IP address".equalsIgnoreCase(maskingOption) && "IP 地址".equalsIgnoreCase(maskingOption)) {
                           }
                        } else if (!"decimal".equalsIgnoreCase(dataType) && !"integer".equalsIgnoreCase(dataType)) {
                           if ("String".equalsIgnoreCase(dataType)) {
                              KeyStrInfo keyStrInfo = new KeyStrInfo();
                              Element stringElt = port.element("STRING_WITHKEY");
                              String maskFormat = stringElt.attributeValue("MASK_FORMAT");
                              String filterSourceCharacters = stringElt.attributeValue("FILTER_SOURCE_CHARACTERS");
                              String filterSourceOption = stringElt.attributeValue("FILTER_SOURCE_OPTION");
                              String sourceCharacters = stringElt.attributeValue("SOURCE_CHARACTERS");
                              String filterTargetCharacters = stringElt.attributeValue("FILTER_TARGET_CHARACTERS");
                              String filterTargetOption = stringElt.attributeValue("FILTER_TARGET_OPTION");
                              String targetCharacters = stringElt.attributeValue("TARGET_CHARACTERS");
                              keyStrInfo.setMaskFormat(maskFormat);
                              keyStrInfo.setFilterSourceCharacters(filterSourceCharacters);
                              keyStrInfo.setFilterSourceOption(filterSourceOption);
                              keyStrInfo.setSourceCharacters(sourceCharacters);
                              keyStrInfo.setFilterTargetCharacters(filterTargetCharacters);
                              keyStrInfo.setFilterTargetOption(filterTargetOption);
                              keyStrInfo.setTargetCharacters(targetCharacters);
                              curInputPortInfo.setKeyStrInfo(keyStrInfo);
                           }
                        } else {
                           Element numericWithkeyElt = port.element("NUMERIC_WITHKEY");
                           String var35 = numericWithkeyElt.attributeValue("IS_PARAMETRIZED");
                        }
                     } else if ("String".equalsIgnoreCase(dataType)) {
                        RandomStrInfo randomStrInfo = new RandomStrInfo();
                        Element stringElt = port.element("STRING");
                        String minimumWidth = stringElt.attributeValue("MINIMUM_WIDTH");
                        String maximumWidth = stringElt.attributeValue("MAXIMUM_WIDTH");
                        String maskFormat = stringElt.attributeValue("MASK_FORMAT");
                        String filterSourceCharacters = stringElt.attributeValue("FILTER_SOURCE_CHARACTERS");
                        String filterSourceOption = stringElt.attributeValue("FILTER_SOURCE_OPTION");
                        String sourceCharacters = stringElt.attributeValue("SOURCE_CHARACTERS");
                        String filterTargetCharacters = stringElt.attributeValue("FILTER_TARGET_CHARACTERS");
                        String filterTargetOption = stringElt.attributeValue("FILTER_TARGET_OPTION");
                        String targetCharacters = stringElt.attributeValue("TARGET_CHARACTERS");
                        randomStrInfo.setMinimumWidth(minimumWidth);
                        randomStrInfo.setMaximumWidth(maximumWidth);
                        randomStrInfo.setMaskFormat(maskFormat);
                        randomStrInfo.setFilterSourceCharacters(filterSourceCharacters);
                        randomStrInfo.setFilterSourceOption(filterSourceOption);
                        randomStrInfo.setSourceCharacters(sourceCharacters);
                        randomStrInfo.setFilterTargetCharacters(filterTargetCharacters);
                        randomStrInfo.setFilterTargetOption(filterTargetOption);
                        randomStrInfo.setTargetCharacters(targetCharacters);
                        curInputPortInfo.setRandomStrInfo(randomStrInfo);
                     } else if ("decimal".equalsIgnoreCase(dataType) || "integer".equalsIgnoreCase(dataType)) {
                        RandomNumInfo randomNumInfo = new RandomNumInfo();
                        Element numericElt = port.element("NUMERIC");
                        String bounds = numericElt.attributeValue("BOUNDS");
                        String minimum = numericElt.attributeValue("MINIMUM");
                        String maximum = numericElt.attributeValue("MAXIMUM");
                        String blurring = numericElt.attributeValue("BLURRING");
                        String blur = numericElt.attributeValue("BLUR");
                        String lowRange = numericElt.attributeValue("LOW_RANGE");
                        String highRange = numericElt.attributeValue("HIGH_RANGE");
                        randomNumInfo.setBounds(bounds);
                        randomNumInfo.setMinimum(minimum);
                        randomNumInfo.setMaximum(maximum);
                        randomNumInfo.setBlurring(blurring);
                        randomNumInfo.setBlur(blur);
                        randomNumInfo.setLowRange(lowRange);
                        randomNumInfo.setHighRange(highRange);
                        curInputPortInfo.setRandomNumInfo(randomNumInfo);
                     }
                  } else {
                     SubstitutionInfo substitutionInfo = new SubstitutionInfo();
                     Element substitution = port.element("SUBSTITUTION");
                     String tablename = substitution.attributeValue("TABLENAME");
                     String columnname = substitution.attributeValue("COLUMNNAME");
                     String inputport = substitution.attributeValue("INPUTPORT");
                     String dictcolumn = substitution.attributeValue("DICTCOLUMN");
                     String isKeyMasked = substitution.attributeValue("IS_KEY_MASKED");
                     String isOutputUnique = substitution.attributeValue("IS_OUTPUT_UNIQUE");
                     String uniqueColumn = substitution.attributeValue("UNIQUE_COLUMN");
                     substitutionInfo.setTablename(tablename);
                     substitutionInfo.setColumnname(columnname);
                     substitutionInfo.setInputport(inputport);
                     substitutionInfo.setDictcolumn(dictcolumn);
                     substitutionInfo.setIsKeyMasked(isKeyMasked);
                     substitutionInfo.setIsOutputUnique(isOutputUnique);
                     substitutionInfo.setUniqueColumn(uniqueColumn);
                     curInputPortInfo.setSubstitutionInfo(substitutionInfo);
                  }
               }
            }
         }
      } catch (Exception e) {
         e.printStackTrace();
      }

   }

   public static void main(String[] args) {
      rulesXmlParsing("sh_telephone");
   }
}
