package com.njcn.gather.icd.mapping.component;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.njcn.gather.icd.mapping.pojo.bo.mapping.DoiItem;
import com.njcn.gather.icd.mapping.pojo.bo.mapping.ReportMapItem;
import com.njcn.gather.icd.mapping.pojo.dto.*;
import com.njcn.gather.icd.mapping.pojo.bo.*;
import com.njcn.gather.icd.mapping.pojo.param.*;
import com.njcn.gather.icd.mapping.pojo.vo.*;
import com.njcn.gather.icd.mapping.pojo.enums.GenerateStatus;
import com.njcn.gather.icd.mapping.pojo.bo.mapping.MappingDocument;
import com.njcn.gather.icd.mapping.utils.GeneratedFileNameUtil;
import io.swagger.models.auth.In;
import lombok.var;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;

/**
 * JSON到XML转换服务。
 * 
 * 职责：
 * 1. 接收JSON格式的MappingDocument
 * 2. 基于规则文件和模板，将JSON数据转换为XML格式
 * 3. 输出最终的XML文件
 */
@Component
public class JsonToXmlConversionService {
    
    private final ObjectMapper objectMapper;
    private final RuleBasedXmlMappingService ruleBasedXmlMappingService;
    
    public JsonToXmlConversionService(RuleBasedXmlMappingService ruleBasedXmlMappingService) {
        this.ruleBasedXmlMappingService = ruleBasedXmlMappingService;
        this.objectMapper = new ObjectMapper();
        this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }


    /**
     * 从 JSON 字符串转换为 XML 内容，供前端直接展示。
     *
     * @param mappingJson JSON 格式的映射文档
     * @param templateStream XML 模板流
     * @param ruleStreams 规则文件流列表
     * @param indexMapping 索引映射配置
     * @param configType pms3.0或者linux前置
     * @return 生成后的 XML 内容
     * @throws Exception 转换异常
     */
    public String buildXmlContentFromJson(String mappingJson,
                                          InputStream templateStream,
                                          List<InputStream> ruleStreams,
                                          IcdToXmlMappingService.IndexMappingConfig indexMapping,
                                          Integer configType,
                                          List<String> methodDescribeList) throws Exception {
        // 反序列化 JSON 后复用现有规则引擎生成 XML，避免文件输出链路重复实现。
        MappingDocument mappingDocument = objectMapper.readValue(mappingJson, MappingDocument.class);
        return buildXmlFromMapping(mappingDocument, templateStream, ruleStreams, indexMapping, configType, methodDescribeList);
    }

    /**
     * 从MappingDocument构建XML内容
     */
    private String buildXmlFromMapping(MappingDocument mappingDocument,
                                       InputStream templateStream,
                                       List<InputStream> ruleStreams,
                                       IcdToXmlMappingService.IndexMappingConfig indexMapping,
                                       Integer configType,
                                       List<String> methodDescribeList) throws Exception {
        // 读取模板
        String templateContent = readInputStreamToString(templateStream);
        //填充IED信息
        String xmlContent = fillIedInfo(templateContent, mappingDocument);
        //填充ReportControls信息
        xmlContent = fillReportControlsFromMapping(xmlContent, mappingDocument);
        //填充do da信息
        xmlContent = applyRulesFromMapping(xmlContent, mappingDocument, ruleStreams, indexMapping, configType,methodDescribeList);
        
        return xmlContent;
    }
    
    private String readInputStreamToString(InputStream inputStream) throws Exception {
        java.io.ByteArrayOutputStream result = new java.io.ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int length;
        while ((length = inputStream.read(buffer)) != -1) {
            result.write(buffer, 0, length);
        }
        return result.toString(StandardCharsets.UTF_8.name());
    }
    
    /**
     * 填充IED信息
     */
    private String fillIedInfo(String xmlContent, MappingDocument mappingDocument) {
        if (mappingDocument == null) {
            return xmlContent;
        }

        String iedName = mappingDocument.getIed();
        String ldPrefix = mappingDocument.getLd();
        String waveTimeFlag = mappingDocument.getWaveTimeFlag();
        if (waveTimeFlag.startsWith("U") || waveTimeFlag.startsWith("u")){
            waveTimeFlag= waveTimeFlag.toUpperCase();
        }else{
            waveTimeFlag= waveTimeFlag.toLowerCase();
        }

        if (iedName != null && !iedName.isEmpty()) {
            xmlContent = xmlContent.replaceAll(
                "<IED\\s+name=\"[^\"]*\"",
                "<IED name=\"" + escapeXml(iedName) + "\""
            );
        }

        if (ldPrefix != null && !ldPrefix.isEmpty()) {
            xmlContent = xmlContent.replaceAll(
                "<LDevice\\s+Prefix=\"[^\"]*\"",
                "<LDevice Prefix=\"" + escapeXml(ldPrefix) + "\""
            );
        }

        // 从 JSON 中读取 WaveTimeFlag 替换模板中的硬编码值
        if (waveTimeFlag != null && !waveTimeFlag.isEmpty()) {
            xmlContent = xmlContent.replaceAll(
                "<ComtradeFile\\s+WaveTimeFlag=\"[^\"]*\"",
                "<ComtradeFile WaveTimeFlag=\"" + escapeXml(waveTimeFlag) + "\""
            );
        }

        return xmlContent;
    }
    
    /**
     * 从MappingDocument填充ReportControl信息
     */
    private String fillReportControlsFromMapping(String xmlContent, MappingDocument mappingDocument) {
        if (mappingDocument == null || mappingDocument.getReportMap() == null || mappingDocument.getReportMap().isEmpty()) {
            return xmlContent;
        }

        StringBuilder reportStatBuilder = new StringBuilder();
        reportStatBuilder.append("\t\t<ReportStat>\n");

        for (var reportItem : mappingDocument.getReportMap()) {
            if (reportItem.getName() != null && !reportItem.getName().isEmpty()) {
                String name = reportItem.getName();
                
                if (name.contains("brcbFluc") ||
                    name.contains("brcbStHarm") ||
                    name.contains("brcbStIHarm") ||
                    name.contains("brcbStMMXU") ||
                    name.contains("brcbStMSQI") ||
                    name.contains("brcbPLT") ||
                    name.contains("brcbPST") ||
                    name.contains("brcbFlicker") ||
                    name.contains("brcbStatistic")) {
                    
                    String reportControlStr = buildReportControlString(reportItem);
                    reportStatBuilder.append("\t\t\t<Report ReportControl=\"")
                        .append(escapeXml(reportControlStr))
                        .append("\" />\n");
                }
            }
        }

        reportStatBuilder.append("\t\t</ReportStat>");

        xmlContent = xmlContent.replaceAll(
            "<ReportStat>[\\s\\S]*?</ReportStat>",
            reportStatBuilder.toString().replace("$", "\\$").replace("[", "\\[").replace("]", "\\]")
        );

        reportStatBuilder = new StringBuilder();
        reportStatBuilder.append("\t\t<ReportReal>\n");

        for (var reportItem : mappingDocument.getReportMap()) {
            if (reportItem.getName() != null && !reportItem.getName().isEmpty()) {
                String name = reportItem.getName();

                if (name.contains("urcbFluc") ||
                        name.contains("brcbFluc") ||
                        name.contains("urcbRtHarm") ||
                        name.contains("urcbRtIHarm") ||
                        name.contains("urcbRtMMXU") ||
                        name.contains("urcbRtMSQI") ||
                        name.contains("urcbPLT") ||
                        name.contains("urcbPST") ||
                        name.contains("brcbPLT") ||
                        name.contains("brcbPST") ||
                        name.contains("urcbFlicker") ||
                        name.contains("urcbStatistic")||
                        name.contains("urcbRealData")) {

                    String reportControlStr = buildReportControlString(reportItem);
                    reportStatBuilder.append("\t\t\t<Report ReportControl=\"")
                            .append(escapeXml(reportControlStr))
                            .append("\" />\n");
                }
            }
        }

        reportStatBuilder.append("\t\t</ReportReal>");

        xmlContent = xmlContent.replaceAll(
                "<ReportReal>[\\s\\S]*?</ReportReal>",
                reportStatBuilder.toString().replace("$", "\\$").replace("[", "\\[").replace("]", "\\]")
        );

        reportStatBuilder = new StringBuilder();
        reportStatBuilder.append("\t\t<ReportEvent>\n");

        for (var reportItem : mappingDocument.getReportMap()) {
            if (reportItem.getName() != null && !reportItem.getName().isEmpty()) {
                String name = reportItem.getName();

                if (name.contains("QVVR") ||
                        name.contains("RDRE") ||
                        name.contains("GGIO")) {

                    String reportControlStr = buildEventReportControlString(reportItem);
                    reportStatBuilder.append("\t\t\t<Report ReportControl=\"")
                            .append(escapeXml(reportControlStr))
                            .append("\" />\n");
                }
            }
        }

        reportStatBuilder.append("\t\t</ReportEvent>");

        xmlContent = xmlContent.replaceAll(
                "<ReportEvent>[\\s\\S]*?</ReportEvent>",
                reportStatBuilder.toString().replace("$", "\\$").replace("[", "\\[").replace("]", "\\]")
        );




        return xmlContent;
    }
    
    /**
     * 构建ReportControl字符串
     */
    private String buildReportControlString(ReportMapItem rc) {
        StringBuilder sb = new StringBuilder();

        sb.append("LLN0$").append(rc.getBuffered() != null && rc.getBuffered().equals("BR") ? "BR$" : "RP$").append(rc.getName());
        if(rc.getName().contains("urcb")){
            sb.append(",3");
        }
        else if(rc.getName().contains("PLT") || rc.getName().contains("Flicker") || rc.getName().contains("PST") || rc.getName().contains("Fluc")){
            sb.append(",600");
        }else{
            sb.append(",60");
        }
        if(rc.getName().contains("urcb")){
            sb.append(",0");
            sb.append(",0");
            sb.append(",0");
            sb.append(",1");
            sb.append(",0");
        }else{
            sb.append(",1");
            sb.append(",0");
            sb.append(",0");
            sb.append(",0");
            sb.append(",0");
        }

        sb.append(",yes");
        sb.append(",1");
        sb.append(",1");
        sb.append(",1");
        sb.append(",1");
        sb.append(",1");
        sb.append(",0");
        sb.append(",1");
        sb.append(",1");
        sb.append(",1");
        sb.append(",3");
        
        if(rc.getName().contains("PLT") || rc.getName().contains("Flicker")){
            sb.append(",1");
        }else if(rc.getName().contains("PST") || rc.getName().contains("Fluc")|| rc.getName().contains("RealData")){
            sb.append(",2");
        }else {
            sb.append(",0");
        }

        return sb.toString();
    }


    /**
     * 构建EventReportControl字符串
     */
    private String buildEventReportControlString(ReportMapItem rc) {
        StringBuilder sb = new StringBuilder();

        sb.append("LLN0$").append(rc.getBuffered() != null && rc.getBuffered().equals("BR") ? "BR$" : "RP$").append(rc.getName());
        if(rc.getName().contains("urcb")){
            sb.append(",3");
        }
        else if(rc.getName().contains("PLT") || rc.getName().contains("Flicker") || rc.getName().contains("PST") || rc.getName().contains("Fluc")){
            sb.append(",600");
        }else{
            sb.append(",60");
        }
        sb.append(",1");
        sb.append(",0");
        sb.append(",0");
        sb.append(",0");
        sb.append(",0");
        sb.append(",yes");
        sb.append(",1");
        sb.append(",1");
        sb.append(",1");
        sb.append(",1");
        sb.append(",1");
        sb.append(",0");
        sb.append(",1");
        sb.append(",1");
        sb.append(",1");
        sb.append(",8");
        sb.append(",1");
        sb.append(",0");

        return sb.toString();
    }

    /**
     * 从MappingDocument应用规则
     */
    private String applyRulesFromMapping(String xmlContent,
                                         MappingDocument mappingDocument,
                                         List<InputStream> ruleStreams,
                                         IcdToXmlMappingService.IndexMappingConfig indexMapping,
                                         Integer configType,
                                         List<String> methodDescribeList) throws Exception {
        //合并所有规则文件
        var mergedRules = mergeAllRulesDesc(ruleStreams, indexMapping);
        //读取mappingDocument
        var mappingMetrics = extractMetricsFromMapping(mappingDocument, configType);
        
        addMethodDescribe(methodDescribeList, "========== 开始从JSON匹配规则 ==========");
        addMethodDescribe(methodDescribeList, "规则文件中定义规则总数: " + mergedRules.size());
        addMethodDescribe(methodDescribeList, "JSON中指标总数: " + mappingMetrics.size());
        
        var applicableRules = findApplicableRulesDesc(mergedRules, mappingMetrics, methodDescribeList);
        
        int xmlValueTagCount = countXmlValueTags(xmlContent);
        int matchedValueTagCount = countMatchedValueTags(xmlContent, applicableRules);
        int unmatchedValueTagCount = xmlValueTagCount - matchedValueTagCount;
        
        addMethodDescribe(methodDescribeList, "========== XML模板配置统计 ==========");
        addMethodDescribe(methodDescribeList, "XML模板中需要配置的<Value>标签总数: " + xmlValueTagCount);
        addMethodDescribe(methodDescribeList, "成功匹配的<Value>标签数: " + matchedValueTagCount);
        addMethodDescribe(methodDescribeList, "未匹配的<Value>标签数: " + unmatchedValueTagCount);
        
        if (unmatchedValueTagCount > 0) {
            List<String> unmatchedDescList = findUnmatchedValueTags(xmlContent, applicableRules);
            addMethodDescribe(methodDescribeList, "未匹配的标签desc列表:");
            for (String desc : unmatchedDescList) {
                addMethodDescribe(methodDescribeList, "  - " + desc);
            }
        }
        
        addMethodDescribe(methodDescribeList, "========== JSON规则匹配结束 ==========");
        
        return applyRulesToXml(xmlContent, applicableRules);
    }
    
    /**
     * 合并所有规则文件
     */
    private java.util.Map<String, List<RuleBasedXmlMappingService.ValueRule>> mergeAllRules(
            List<InputStream> ruleStreams,
            IcdToXmlMappingService.IndexMappingConfig indexMapping) throws Exception {
        
        java.util.Map<String, List<RuleBasedXmlMappingService.ValueRule>> mergedRules = new java.util.LinkedHashMap<>();
        
        for (InputStream ruleStream : ruleStreams) {
            var rules = parseRuleFile(ruleStream, indexMapping);
            for (var entry : rules.entrySet()) {
                String key = entry.getKey();
                List<RuleBasedXmlMappingService.ValueRule> ruleList = entry.getValue();
                mergedRules.computeIfAbsent(key, k -> new ArrayList<>()).addAll(ruleList);
            }
        }
        
        return mergedRules;
    }

    private java.util.Map<String, List<RuleBasedXmlMappingService.ValueRule>> mergeAllRulesDesc(
            List<InputStream> ruleStreams,
            IcdToXmlMappingService.IndexMappingConfig indexMapping) throws Exception {

        java.util.Map<String, List<RuleBasedXmlMappingService.ValueRule>> mergedRules = new java.util.LinkedHashMap<>();

        for (InputStream ruleStream : ruleStreams) {
            var rules = parseRuleFileDesc(ruleStream, indexMapping);
            for (var entry : rules.entrySet()) {
                String key = entry.getKey();
                List<RuleBasedXmlMappingService.ValueRule> ruleList = entry.getValue();
                mergedRules.computeIfAbsent(key, k -> new ArrayList<>()).addAll(ruleList);
            }
        }

        return mergedRules;
    }
    
    /**
     * 解析规则文件
     */
    private java.util.Map<String, List<RuleBasedXmlMappingService.ValueRule>> parseRuleFile(
            InputStream ruleStream,
            IcdToXmlMappingService.IndexMappingConfig indexMapping) throws Exception {
        
        java.util.Map<String, List<RuleBasedXmlMappingService.ValueRule>> rules = new java.util.HashMap<>();
        
        java.io.BufferedReader reader = new java.io.BufferedReader(
            new java.io.InputStreamReader(ruleStream, StandardCharsets.UTF_8)
        );
        
        String line;
        String currentGroup = "";
        
        java.util.regex.Pattern valueRulePattern = java.util.regex.Pattern.compile(
            "<Value\\s+" +
            "name=\"([^\"]+)\"\\s+" +
            "desc=\"([^\"]+)\"\\s+" +
            "type=\"([^\"]+)\"\\s+" +
            "(?:DO=\"([^\"]*)\")?\\s*" +
            "(?:DA=\"([^\"]*)\")?\\s*" +
            "(?:BaseFlag=\"([^\"]*)\")?\\s*" +
            "(?:LimitUp=\"([^\"]*)\")?\\s*" +
            "(?:LimitDown=\"([^\"]*)\")?\\s*" +
            "(?:Coefficient=\"([^\"]*)\")?\\s*" +
            "/>", java.util.regex.Pattern.CASE_INSENSITIVE
        );
        
        while ((line = reader.readLine()) != null) {
            line = line.trim();
            
            if (line.startsWith("<!--")) {
                if (line.contains("MMXU") || line.contains("基本数据")) {
                    currentGroup = "MMXU";
                } else if (line.contains("间谐波")) {
                    currentGroup = "INTER_HARMONIC";
                } else if (line.contains("MHAI") && line.contains("谐波数据")) {
                    currentGroup = "MHAI";
                } else if (line.contains("MSQI") || line.contains("序分量")) {
                    currentGroup = "MSQI";
                } else if (line.contains("短闪") || line.contains("短时闪变")) {
                    currentGroup = "MFLK_SHORT";
                } else if (line.contains("长闪") || line.contains("长时闪变")) {
                    currentGroup = "MFLK_LONG";
                } else if (line.contains("QVVR") || line.contains("电压变动")) {
                    currentGroup = "QVVR";
                }
                continue;
            }
            
            if (line.isEmpty() || !line.startsWith("<Value")) {
                continue;
            }
            
            java.util.regex.Matcher matcher = valueRulePattern.matcher(line);
            if (matcher.find()) {
                RuleBasedXmlMappingService.ValueRule rule = new RuleBasedXmlMappingService.ValueRule();
                rule.setName(matcher.group(1));
                rule.setDesc(matcher.group(2));
                rule.setType(matcher.group(3));
                String doPath = matcher.group(4) != null ? matcher.group(4) : "";
                String daPath = matcher.group(5) != null ? matcher.group(5) : "";
                
                if (indexMapping != null && !doPath.isEmpty()) {
                    doPath = applyIndexMapping(doPath, currentGroup, indexMapping, rule.getName(), rule.getDesc());
                }
                
                rule.setDoPath(doPath);
                rule.setDaPath(daPath);
                rule.setBaseFlag(matcher.group(6));
                rule.setLimitUp(matcher.group(7));
                rule.setLimitDown(matcher.group(8));
                rule.setCoefficient(matcher.group(9));
                
                String key = buildRuleKey(rule.getName(), rule.getDesc());
                if (!key.isEmpty() && hasValidDoOrDa(rule)) {
                    rules.computeIfAbsent(key.toLowerCase(), k -> new ArrayList<>()).add(rule);
                }
            }
        }
        
        reader.close();
        return rules;
    }

    private java.util.Map<String, List<RuleBasedXmlMappingService.ValueRule>> parseRuleFileDesc(
            InputStream ruleStream,
            IcdToXmlMappingService.IndexMappingConfig indexMapping) throws Exception {

        java.util.Map<String, List<RuleBasedXmlMappingService.ValueRule>> rules = new java.util.HashMap<>();

        java.io.BufferedReader reader = new java.io.BufferedReader(
                new java.io.InputStreamReader(ruleStream, StandardCharsets.UTF_8)
        );

        String line;
        String currentGroup = "";

        java.util.regex.Pattern valueTagPattern = java.util.regex.Pattern.compile(
                "<Value\\s+([^>]+)/>", 
                java.util.regex.Pattern.CASE_INSENSITIVE
        );
        
        java.util.regex.Pattern attributePattern = java.util.regex.Pattern.compile(
                "(name|desc|type|DO|DA|BaseFlag|LimitUp|LimitDown|Coefficient|Offset|PltFlag)=\"([^\"]*)\"",
                java.util.regex.Pattern.CASE_INSENSITIVE
        );

        while ((line = reader.readLine()) != null) {
            line = line.trim();

            if (line.startsWith("<!--")) {
                if (line.contains("MMXU") || line.contains("基本数据")) {
                    currentGroup = "MMXU";
                } else if (line.contains("间谐波")) {
                    currentGroup = "INTER_HARMONIC";
                } else if (line.contains("MHAI") && line.contains("谐波数据")) {
                    currentGroup = "MHAI";
                } else if (line.contains("MSQI") || line.contains("序分量")) {
                    currentGroup = "MSQI";
                } else if (line.contains("短闪") || line.contains("短时闪变")) {
                    currentGroup = "MFLK_SHORT";
                } else if (line.contains("长闪") || line.contains("长时闪变")) {
                    currentGroup = "MFLK_LONG";
                } else if (line.contains("QVVR") || line.contains("电压变动")) {
                    currentGroup = "QVVR";
                }
                continue;
            }

            if (line.isEmpty() || !line.startsWith("<Value")) {
                continue;
            }

            java.util.regex.Matcher tagMatcher = valueTagPattern.matcher(line);
            if (tagMatcher.find()) {
                String attributesStr = tagMatcher.group(1);
                
                java.util.Map<String, String> attrMap = new java.util.HashMap<>();
                java.util.regex.Matcher attrMatcher = attributePattern.matcher(attributesStr);
                while (attrMatcher.find()) {
                    attrMap.put(attrMatcher.group(1).toLowerCase(), attrMatcher.group(2));
                }
                
                RuleBasedXmlMappingService.ValueRule rule = new RuleBasedXmlMappingService.ValueRule();
                rule.setName(attrMap.getOrDefault("name", ""));
                rule.setDesc(attrMap.getOrDefault("desc", ""));
                rule.setType(attrMap.getOrDefault("type", ""));
                
                String doPath = attrMap.getOrDefault("do", "");
                String daPath = attrMap.getOrDefault("da", "");

                if (indexMapping != null && !doPath.isEmpty()) {
                    doPath = applyIndexMapping(doPath, currentGroup, indexMapping, rule.getName(), rule.getDesc());
                }

                rule.setDoPath(doPath);
                rule.setDaPath(daPath);
                rule.setBaseFlag(attrMap.getOrDefault("baseflag", null));
                rule.setLimitUp(attrMap.getOrDefault("limitup", null));
                rule.setLimitDown(attrMap.getOrDefault("limitdown", null));
                rule.setCoefficient(attrMap.getOrDefault("coefficient", null));
                rule.setOffset(attrMap.getOrDefault("offset", null));
                rule.setPltFlag(attrMap.getOrDefault("pltflag", null));

                String key =  rule.getDesc();

                if (!key.isEmpty()) {//!key.isEmpty() && hasValidDoOrDa(rule)
                    rules.computeIfAbsent(key.toLowerCase(), k -> new ArrayList<>()).add(rule);
                }
            }
        }

        reader.close();
        return rules;
    }



    /**
     * 应用索引映射
     */
    private String applyIndexMapping(String doPath, String currentGroup,
                                     IcdToXmlMappingService.IndexMappingConfig indexMapping,
                                     String name, String desc) {
        if (indexMapping == null) {
            return doPath;
        }
        
        java.util.regex.Pattern doIndexPattern = java.util.regex.Pattern.compile("(MMXU|MHAI|MSQI|MFLK|QVVR)(\\d+)");
        java.util.regex.Pattern doNoIndexPattern = java.util.regex.Pattern.compile("(MMXU|MHAI|MSQI|MFLK|QVVR)\\$");
        
        java.util.regex.Matcher matcherWithIndex = doIndexPattern.matcher(doPath);
        if (matcherWithIndex.find()) {
            String lnClass = matcherWithIndex.group(1);
            int originalIndex = Integer.parseInt(matcherWithIndex.group(2));
            
            int newIndex = determineNewIndex(currentGroup, lnClass, originalIndex, indexMapping, name, desc);
            
            if (newIndex >= 0) {
                return matcherWithIndex.replaceAll(lnClass + newIndex);
            }
            
            return doPath;
        }
        
        java.util.regex.Matcher matcherNoIndex = doNoIndexPattern.matcher(doPath);
        if (matcherNoIndex.find()) {
            String lnClass = matcherNoIndex.group(1);
            
            int newIndex = determineNewIndex(currentGroup, lnClass, 0, indexMapping, name, desc);
            
            if (newIndex >= 0) {
                return matcherNoIndex.replaceAll(lnClass + newIndex + "\\$");
            }
        }
        
        return doPath;
    }
    
    /**
     * 确定新索引
     */
    private int determineNewIndex(String currentGroup, String lnClass, int originalIndex,
                                  IcdToXmlMappingService.IndexMappingConfig indexMapping,
                                  String name, String desc) {
        if (indexMapping == null) {
            return originalIndex;
        }
        
        String lowerName = (name != null ? name : "").toLowerCase();
        String lowerDesc = (desc != null ? desc : "").toLowerCase();
        
        boolean isAverage = lowerName.contains("avg") || lowerDesc.contains("平均值");
        boolean isMaximum = lowerName.startsWith("max_") || lowerDesc.contains("最大值");
        boolean isMinimum = lowerName.startsWith("min_") || lowerDesc.contains("最小值");
        boolean is95Percentile = lowerName.startsWith("g_") || lowerDesc.contains("95值");
        
        boolean isInterHarmonic = lowerDesc.contains("间谐波");
        
        if ("MMXU".equals(currentGroup) || "MMXU".equals(lnClass)) {
            IcdToXmlMappingService.IndexMappingConfig.StatIndex mmxu = indexMapping.getMmxu();
            if (mmxu != null) {
                if (isAverage && mmxu.getAverage() != null) return mmxu.getAverage();
                if (isMaximum && mmxu.getMaximum() != null) return mmxu.getMaximum();
                if (isMinimum && mmxu.getMinimum() != null) return mmxu.getMinimum();
                if (is95Percentile && mmxu.getPercentile95() != null) return mmxu.getPercentile95();
            }
        }
        
        if ("INTER_HARMONIC".equals(currentGroup) || isInterHarmonic) {
            IcdToXmlMappingService.IndexMappingConfig.StatIndex interHarmonic = indexMapping.getInterHarmonic();
            if (interHarmonic != null) {
                if (isAverage && interHarmonic.getAverage() != null) return interHarmonic.getAverage();
                if (isMaximum && interHarmonic.getMaximum() != null) return interHarmonic.getMaximum();
                if (isMinimum && interHarmonic.getMinimum() != null) return interHarmonic.getMinimum();
                if (is95Percentile && interHarmonic.getPercentile95() != null) return interHarmonic.getPercentile95();
            }
        }
        
        if ("MHAI".equals(currentGroup) && !isInterHarmonic) {
            IcdToXmlMappingService.IndexMappingConfig.StatIndex mhai = indexMapping.getMhai();
            if (mhai != null) {
                if (isAverage && mhai.getAverage() != null) return mhai.getAverage();
                if (isMaximum && mhai.getMaximum() != null) return mhai.getMaximum();
                if (isMinimum && mhai.getMinimum() != null) return mhai.getMinimum();
                if (is95Percentile && mhai.getPercentile95() != null) return mhai.getPercentile95();
            }
        }
        
        if ("MSQI".equals(currentGroup) || "MSQI".equals(lnClass)) {
            IcdToXmlMappingService.IndexMappingConfig.StatIndex msqi = indexMapping.getMsqi();
            if (msqi != null) {
                if (isAverage && msqi.getAverage() != null) return msqi.getAverage();
                if (isMaximum && msqi.getMaximum() != null) return msqi.getMaximum();
                if (isMinimum && msqi.getMinimum() != null) return msqi.getMinimum();
                if (is95Percentile && msqi.getPercentile95() != null) return msqi.getPercentile95();
            }
        }
        
        if ("MFLK_SHORT".equals(currentGroup)) {
            if (indexMapping.getMflkShort() != null) {
                return indexMapping.getMflkShort();
            }
        }
        
        if ("MFLK_LONG".equals(currentGroup)) {
            if (indexMapping.getMflkLong() != null) {
                return indexMapping.getMflkLong();
            }
        }
        
        if ("QVVR".equals(currentGroup) || "QVVR".equals(lnClass)) {
            if (indexMapping.getQvvr() != null) {
                return indexMapping.getQvvr();
            }
        }
        
        return originalIndex;
    }
    
    /**
     * 构建规则键
     */
    private String buildRuleKey(String name, String desc) {
        if (name != null && !name.isEmpty()) {
            return name;
        }
        return desc != null ? desc : "";
    }
    
    /**
     * 检查是否有有效的DO或DA
     */
    private boolean hasValidDoOrDa(RuleBasedXmlMappingService.ValueRule rule) {
        return (rule.getDoPath() != null && !rule.getDoPath().isEmpty()) ||
               (rule.getDaPath() != null && !rule.getDaPath().isEmpty());
    }
    
    /**
     * 从MappingDocument提取指标信息
     */
    private java.util.Map<String, MetricInfo> extractMetricsFromMapping(MappingDocument mappingDocument,Integer configType) {
        java.util.Map<String, MetricInfo> metrics = new java.util.HashMap<>();
        
        if (mappingDocument == null || mappingDocument.getDataSetList() == null) {
            return metrics;
        }
        
        for (var dataSetGroup : mappingDocument.getDataSetList()) {
            if (dataSetGroup.getInstList() == null) continue;
            
            for (var instItem : dataSetGroup.getInstList()) {
                if (instItem.getDoiList() == null) continue;
                
                for (var doiItem : instItem.getDoiList()) {
                    String doPath = buildDoPath(dataSetGroup.getLnClass(), instItem.getInst(), doiItem.getName());
                    
                    if (doiItem.getSdiList() != null) {
                        for (var sdiItem : doiItem.getSdiList()) {
                            if (sdiItem.getTypeList() != null) {
                                for (var typeItem : sdiItem.getTypeList()) {
                                    String fullKey = doiItem.getDesc()  + instItem.getDesc()+typeItem.getDesc();
                                    if(fullKey.contains("正序")){
                                        fullKey = doiItem.getDesc()  + instItem.getDesc()+sdiItem.getDesc()+typeItem.getDesc();
                                    }
                                    if(metrics.containsKey(fullKey)){
                                        continue;
                                    }
                                    String daPath = buildDaPath(sdiItem.getName(), typeItem.getName(), doiItem);
                                    if(2==configType && fullKey.contains("线电压总有效值")){
                                        daPath = "1_" + daPath;
                                    }
                                    int offset=calculateOffset(sdiItem.getName(), typeItem.getName(), doiItem);
                                    MetricInfo info = new MetricInfo();
                                    info.setLnClass(dataSetGroup.getLnClass());
                                    info.setLnInst(instItem.getInst());
                                    info.setDoName(doiItem.getName());
                                    info.setDoPath(doPath);
                                    info.setDaPath(daPath);
                                    info.setBaseCount(doiItem.getBasecount());
                                    info.setStart(doiItem.getStart());
                                    info.setEnd(doiItem.getEnd());
                                    info.setBaseFlag(doiItem.getBaseflag());
                                    info.setOffset(offset);
                                    metrics.put(fullKey.toLowerCase(), info);
                                }
                            }
                        }
                    }
                }
            }
        }
        
        return metrics;
    }
    
    /**
     * 构建DO路径
     */
    private String buildDoPath(String lnClass, String lnInst, String doName) {
        StringBuilder sb = new StringBuilder();
        if (lnClass != null) {
            sb.append(lnClass);
        }
        if (lnInst != null) {
            sb.append(lnInst);
        }
        if (doName != null) {
            if (sb.length() > 0) {
                sb.append("$");
                sb.append("MX");
                sb.append("$");
            }
            sb.append(doName);
        }
        return sb.toString();
    }
    
    /**
     * 构建DA路径
     */
    private String buildDaPath(String sdiName, String typeName, DoiItem doiItem) {
        StringBuilder sb = new StringBuilder();
        if (sdiName != null && !sdiName.isEmpty()) {
            String normalizedSdi = normalizePhaseName(sdiName);
            sb.append(normalizedSdi);
            
            if (sdiName.endsWith("Har") && doiItem != null) {
                int baseflag = doiItem.getBaseflag();
                int start = doiItem.getStart();
                
                if (baseflag == 1) {
                    boolean isInterHarmonic = isInterHarmonicMetric(doiItem);//间谐波判断
                    int m = isInterHarmonic ? 0 : 2;
                    int i = m - start;
                    //判断是Offset是否需要
                    if(i<0){
                        sb.append("[%-0]");
                    }else {
                        sb.append("[%-").append(i).append("]");
                    }
                } else {
                    sb.append("[").append(start).append("]");
                }
            }else{
                sb.append("$cVal");
            }
        }
        if (typeName != null && !typeName.isEmpty()) {
            if (sb.length() > 0) {
                sb.append("$");
            }
            sb.append(typeName);
        }
        return sb.toString();
    }

    private int calculateOffset(String sdiName, String typeName, DoiItem doiItem) {
        int offset=0;
        if (sdiName != null && !sdiName.isEmpty()){
            if (sdiName.endsWith("Har") && doiItem != null) {
                int baseflag = doiItem.getBaseflag();
                int start = doiItem.getStart();
                if (baseflag == 1) {
                    boolean isInterHarmonic = isInterHarmonicMetric(doiItem);//间谐波判断
                    int m = isInterHarmonic ? 0 : 2;
                    int i = m - start;

                    //判断是Offset是否需要
                    if(i<0){
                        offset = i;
                    }
                }
            }
        }

        return offset;
    }
    
    /**
     * 标准化相别名称，将具体相别转换为通配符格式
     * - phsA, phsB, phsC, phsAB, phsBC, phsCA -> phs*
     * - phsAHar, phsBHar, phsCHar, phsABHar, phsBCHar, phsCAHar -> phs*Har
     */
    private String normalizePhaseName(String name) {
        if (name == null || name.isEmpty()) {
            return name;
        }
        
        if (name.startsWith("phs")) {
            if (name.endsWith("Har")) {
                return "phs*Har";
            } else {
                return "phs*";
            }
        }
        
        return name;
    }
    
    /**
     * 判断是否为间谐波指标
     */
    private boolean isInterHarmonicMetric(DoiItem doiItem) {
        if (doiItem == null || doiItem.getDesc() == null) {
            return false;
        }
        return doiItem.getDesc().toLowerCase().contains("间谐波");
    }
    
    /**
     * 查找适用的规则
     */
    private java.util.Map<String, RuleBasedXmlMappingService.ValueRule> findApplicableRulesDesc(
            java.util.Map<String, List<RuleBasedXmlMappingService.ValueRule>> allRules,
            java.util.Map<String, MetricInfo> mappingMetrics,
            List<String> methodDescribeList) {

        java.util.Map<String, RuleBasedXmlMappingService.ValueRule> applicable = new java.util.HashMap<>();
        List<String> failedRules = new ArrayList<>();

        for (var entry : allRules.entrySet()) {
            String ruleKey = entry.getKey();
            List<RuleBasedXmlMappingService.ValueRule> ruleVariants = entry.getValue();

            boolean matched = false;

            for (RuleBasedXmlMappingService.ValueRule rule : ruleVariants) {
//                if (rule.getName() == null || rule.getDoPath().isEmpty()) {
//                    continue;
//                }

                if(mappingMetrics.containsKey(rule.getName())){
                    MetricInfo metric = mappingMetrics.get(rule.getName());
                    rule.setDoPath(metric.getDoPath());
                    rule.setDaPath(metric.getDaPath());
                    // 传递offset值，将Integer转换为String
                    rule.setOffset(String.valueOf(metric.getOffset()));
                    applicable.put(ruleKey, rule);
                    matched = true;
                    addMethodDescribe(methodDescribeList, "✓ 规则匹配成功: " + ruleKey + " -> DO=" + rule.getDoPath() + ", DA=" + rule.getDaPath());

                }


                if (matched) {
                    break;
                }
            }

            if (!matched) {
                failedRules.add(ruleKey);
                addMethodDescribe(methodDescribeList, "✗ 规则匹配失败: " + ruleKey + " (共" + ruleVariants.size() + "个候选)");
                for (RuleBasedXmlMappingService.ValueRule rule : ruleVariants) {
                    addMethodDescribe(methodDescribeList, "  候选指标名: " + rule.getName());
                }
            }
        }

        addMethodDescribe(methodDescribeList, "========== 详细匹配结果 ==========");
        addMethodDescribe(methodDescribeList, "成功匹配的规则 (" + applicable.size() + " 条):");
        for (String key : applicable.keySet()) {
            addMethodDescribe(methodDescribeList, "  - " + key);
        }

        addMethodDescribe(methodDescribeList, "失败匹配的规则 (" + failedRules.size() + " 条):");
        for (String key : failedRules) {
            addMethodDescribe(methodDescribeList, "  - " + key);
        }

        return applicable;
    }



    private java.util.Map<String, RuleBasedXmlMappingService.ValueRule> findApplicableRules(
            java.util.Map<String, List<RuleBasedXmlMappingService.ValueRule>> allRules,
            java.util.Map<String, MetricInfo> mappingMetrics) {

        java.util.Map<String, RuleBasedXmlMappingService.ValueRule> applicable = new java.util.HashMap<>();
        List<String> failedRules = new ArrayList<>();

        for (var entry : allRules.entrySet()) {
            String ruleKey = entry.getKey();
            List<RuleBasedXmlMappingService.ValueRule> ruleVariants = entry.getValue();

            boolean matched = false;

            for (RuleBasedXmlMappingService.ValueRule rule : ruleVariants) {
                if (rule.getDoPath() == null || rule.getDoPath().isEmpty()) {
                    continue;
                }

                String ruleDo = normalizePath(rule.getDoPath());
                String ruleDa = normalizePath(rule.getDaPath());

                for (var metricEntry : mappingMetrics.entrySet()) {
                    MetricInfo metric = metricEntry.getValue();

                    String icdDo = normalizePath(metric.getDoPath());
                    String icdDa = normalizePath(metric.getDaPath());

                    if (matchesPattern(ruleDo, icdDo) && matchesPattern(ruleDa, icdDa)) {
                        applicable.put(ruleKey, rule);
                        matched = true;
                        addMethodDescribe(null, "✓ 规则匹配成功: " + ruleKey + " -> DO=" + rule.getDoPath() + ", DA=" + rule.getDaPath());
                        break;
                    }
                }

                if (matched) {
                    break;
                }
            }

            if (!matched) {
                failedRules.add(ruleKey);
                addMethodDescribe(null, "✗ 规则匹配失败: " + ruleKey + " (共" + ruleVariants.size() + "个候选)");
                for (RuleBasedXmlMappingService.ValueRule rule : ruleVariants) {
                    addMethodDescribe(null, "  候选: DO=" + rule.getDoPath() + ", DA=" + rule.getDaPath());
                }
            }
        }

        addMethodDescribe(null, "========== 详细匹配结果 ==========");
        addMethodDescribe(null, "成功匹配的规则 (" + applicable.size() + " 条):");
        for (String key : applicable.keySet()) {
            addMethodDescribe(null, "  - " + key);
        }

        addMethodDescribe(null, "失败匹配的规则 (" + failedRules.size() + " 条):");
        for (String key : failedRules) {
            addMethodDescribe(null, "  - " + key);
        }

        return applicable;
    }
    
    /**
     * 标准化路径
     */
    private String normalizePath(String path) {
        if (path == null) return "";
        return path.trim().toLowerCase();
    }
    
    /**
     * 匹配模式
     */
    private boolean matchesPattern(String pattern, String actual) {
        if (pattern == null || actual == null) {
            return pattern == null && actual == null;
        }
        
        String normalizedPattern = pattern.replaceAll("\\[[^\\]]*\\]", "");
        
        if (normalizedPattern.isEmpty() || actual.isEmpty()) {
            return normalizedPattern.isEmpty() && actual.isEmpty();
        }

        return actual.equals(normalizedPattern);
    }
    
    /**
     * 应用规则到XML
     */
    private String applyRulesToXml(String xmlContent,
                                   java.util.Map<String, RuleBasedXmlMappingService.ValueRule> applicableRules) {
        
        java.util.regex.Pattern valueTagPattern = java.util.regex.Pattern.compile(
            "<Value\\s+([^>]+)/>", 
            java.util.regex.Pattern.CASE_INSENSITIVE
        );
        
        java.util.regex.Pattern attributePattern = java.util.regex.Pattern.compile(
            "(name|desc|type|DO|DA|BaseFlag|LimitUp|LimitDown|Coefficient|Offset|PltFlag)=\"([^\"]*)\"",
            java.util.regex.Pattern.CASE_INSENSITIVE
        );
        
        java.util.regex.Matcher matcher = valueTagPattern.matcher(xmlContent);
        StringBuffer result = new StringBuffer();
        
        while (matcher.find()) {
            String attributesStr = matcher.group(1);
            
            java.util.Map<String, String> attrMap = new java.util.HashMap<>();
            java.util.regex.Matcher attrMatcher = attributePattern.matcher(attributesStr);
            while (attrMatcher.find()) {
                attrMap.put(attrMatcher.group(1).toLowerCase(), attrMatcher.group(2));
            }
            
            String name = attrMap.getOrDefault("name", "");
            String desc = attrMap.getOrDefault("desc", "");
            String type = attrMap.getOrDefault("type", "6");

            RuleBasedXmlMappingService.ValueRule matchedRule = applicableRules.get(desc);
            if (matchedRule != null) {
                StringBuilder valueNode = new StringBuilder("<Value ");
                // 如果offset<0，需要调整指标名中的%int或int%格式
                String adjustedName = adjustPathWithOffset(name, matchedRule.getOffset());
                valueNode.append("name=\"").append(escapeXml(adjustedName)).append("\" ");
                valueNode.append("desc=\"").append(escapeXml(desc)).append("\" ");
                valueNode.append("type=\"").append(type).append("\" ");
                if (matchedRule.getDoPath() != null && !matchedRule.getDoPath().isEmpty()) {
                    valueNode.append("DO=\"").append(escapeXml(matchedRule.getDoPath())).append("\" ");
                }
                if (matchedRule.getDaPath() != null && !matchedRule.getDaPath().isEmpty()) {
                    valueNode.append("DA=\"").append(escapeXml(matchedRule.getDaPath())).append("\" ");
                }
                if (matchedRule.getBaseFlag() != null && !matchedRule.getBaseFlag().isEmpty()) {
                    valueNode.append("BaseFlag=\"").append(escapeXml(matchedRule.getBaseFlag())).append("\" ");
                }
                if (matchedRule.getLimitUp() != null && !matchedRule.getLimitUp().isEmpty()) {
                    valueNode.append("LimitUp=\"").append(escapeXml(matchedRule.getLimitUp())).append("\" ");
                }
                if (matchedRule.getLimitDown() != null && !matchedRule.getLimitDown().isEmpty()) {
                    valueNode.append("LimitDown=\"").append(escapeXml(matchedRule.getLimitDown())).append("\" ");
                }
                if (matchedRule.getCoefficient() != null && !matchedRule.getCoefficient().isEmpty()) {
                    valueNode.append("Coefficient=\"").append(escapeXml(matchedRule.getCoefficient())).append("\" ");
                }
                if (matchedRule.getOffset() != null && !matchedRule.getOffset().isEmpty() && !matchedRule.getOffset().equals("0")) {
                    valueNode.append("Offset=\"").append(escapeXml(matchedRule.getOffset())).append("\" ");
                }
                if (matchedRule.getPltFlag() != null && !matchedRule.getPltFlag().isEmpty()) {
                    valueNode.append("PltFlag=\"").append(escapeXml(matchedRule.getPltFlag())).append("\" ");
                }
                
                valueNode.append("/>");
                matcher.appendReplacement(result, java.util.regex.Matcher.quoteReplacement(valueNode.toString()));
            }
        }
        matcher.appendTail(result);
        
        return result.toString();
    }
    
    /**
     * XML转义
     */
    private String escapeXml(String text) {
        if (text == null) return "";
        return text.replace("&", "&amp;")
                   .replace("<", "&lt;")
                   .replace(">", "&gt;")
                   .replace("\"", "&quot;")
                   .replace("'", "&apos;");
    }
    
    /**
     * 根据offset调整路径（DO或DA）
     * 当offset<0时，对路径中的[%-int]或[int%]格式增加-offset的值
     * @param path 原始路径（DO或DA）
     * @param offsetStr offset字符串值
     * @return 调整后的路径
     */
    private String adjustPathWithOffset(String path, String offsetStr) {
        if (path == null || offsetStr == null || offsetStr.isEmpty()) {
            return path;
        }
        
        try {
            int offset = Integer.parseInt(offsetStr);
            // 只有当offset<0时才需要调整
            if (offset >= 0) {
                return path;
            }
            
            int adjustment = -offset;

            // 匹配 %数字,数字% 格式并调整（如 %0,49%）
            java.util.regex.Pattern pattern3 = java.util.regex.Pattern.compile("%(\\d+),(\\d+)%");
            java.util.regex.Matcher matcher3 = pattern3.matcher(path);
            StringBuffer result3 = new StringBuffer();
            while (matcher3.find()) {
                int startVal = Integer.parseInt(matcher3.group(1));
                int endVal = Integer.parseInt(matcher3.group(2));
                int newStart = startVal + adjustment;
                int newEnd = endVal + adjustment;
                matcher3.appendReplacement(result3, "%"+newStart+","+newEnd+"%");
            }
            matcher3.appendTail(result3);
            path = result3.toString();
            
            return path;
        } catch (NumberFormatException e) {
            // 如果offset无法解析为整数，返回原始路径
            return path;
        }
    }

    private void addMethodDescribe(List<String> methodDescribeList, String message) {
        if (methodDescribeList == null || message == null || message.trim().isEmpty()) {
            return;
        }
        methodDescribeList.add(message);
    }

    /**
     * 统计 XML 模板中 <Value> 标签的总数
     */
    private int countXmlValueTags(String xmlContent) {
        if (xmlContent == null || xmlContent.isEmpty()) {
            return 0;
        }
        
        java.util.regex.Pattern valueTagPattern = java.util.regex.Pattern.compile(
            "<Value\\s+[^>]+/>", 
            java.util.regex.Pattern.CASE_INSENSITIVE
        );
        
        java.util.regex.Matcher matcher = valueTagPattern.matcher(xmlContent);
        int count = 0;
        while (matcher.find()) {
            count++;
        }
        
        return count;
    }

    /**
     * 统计 XML 模板中成功匹配的 <Value> 标签数
     */
    private int countMatchedValueTags(String xmlContent,
                                      java.util.Map<String, RuleBasedXmlMappingService.ValueRule> applicableRules) {
        if (xmlContent == null || xmlContent.isEmpty() || applicableRules == null) {
            return 0;
        }
        
        java.util.regex.Pattern valueTagPattern = java.util.regex.Pattern.compile(
            "<Value\\s+([^>]+)/>", 
            java.util.regex.Pattern.CASE_INSENSITIVE
        );
        
        java.util.regex.Pattern attributePattern = java.util.regex.Pattern.compile(
            "desc=\"([^\"]*)\"",
            java.util.regex.Pattern.CASE_INSENSITIVE
        );
        
        java.util.regex.Matcher matcher = valueTagPattern.matcher(xmlContent);
        int matchedCount = 0;
        
        while (matcher.find()) {
            String attributesStr = matcher.group(1);
            java.util.regex.Matcher attrMatcher = attributePattern.matcher(attributesStr);
            if (attrMatcher.find()) {
                String desc = attrMatcher.group(1);
                if (applicableRules.containsKey(desc)) {
                    matchedCount++;
                }
            }
        }
        
        return matchedCount;
    }

    /**
     * 查找 XML 模板中未匹配的 <Value> 标签的 desc 属性列表
     */
    private List<String> findUnmatchedValueTags(String xmlContent,
                                                 java.util.Map<String, RuleBasedXmlMappingService.ValueRule> applicableRules) {
        List<String> unmatchedList = new ArrayList<>();
        
        if (xmlContent == null || xmlContent.isEmpty() || applicableRules == null) {
            return unmatchedList;
        }
        
        java.util.regex.Pattern valueTagPattern = java.util.regex.Pattern.compile(
            "<Value\\s+([^>]+)/>", 
            java.util.regex.Pattern.CASE_INSENSITIVE
        );
        
        java.util.regex.Pattern attributePattern = java.util.regex.Pattern.compile(
            "desc=\"([^\"]*)\"",
            java.util.regex.Pattern.CASE_INSENSITIVE
        );
        
        java.util.regex.Matcher matcher = valueTagPattern.matcher(xmlContent);
        
        while (matcher.find()) {
            String attributesStr = matcher.group(1);
            java.util.regex.Matcher attrMatcher = attributePattern.matcher(attributesStr);
            if (attrMatcher.find()) {
                String desc = attrMatcher.group(1);
                if (!applicableRules.containsKey(desc) && !desc.isEmpty()) {
                    unmatchedList.add(desc);
                }
            }
        }
        
        return unmatchedList;
    }

    /**
     * 指标信息内部类
     */
    static class MetricInfo {
        private String lnClass;
        private String lnInst;
        private String doName;
        private String doPath;
        private String daPath;
        private int start;
        private int end;
        private int baseCount;
        private int baseFlag;
        private int offset;
        public int getOffset() {return offset;}
        public void setOffset(int offset) {this.offset = offset;}
        public String getLnClass() { return lnClass; }
        public void setLnClass(String lnClass) { this.lnClass = lnClass; }
        public String getLnInst() { return lnInst; }
        public void setLnInst(String lnInst) { this.lnInst = lnInst; }
        public String getDoName() { return doName; }
        public void setDoName(String doName) { this.doName = doName; }
        public String getDoPath() { return doPath; }
        public void setDoPath(String doPath) { this.doPath = doPath; }
        public String getDaPath() { return daPath; }
        public void setDaPath(String daPath) { this.daPath = daPath; }
        public int getStart() {
            return start;
        }

        public int getEnd() {
            return end;
        }

        public int getBaseCount() {
            return baseCount;
        }

        public int getBaseFlag() {
            return baseFlag;
        }
        public void setStart(int start) {
            this.start = start;
        }

        public void setEnd(int end) {
            this.end = end;
        }

        public void setBaseCount(int baseCount) {
            this.baseCount = baseCount;
        }

        public void setBaseFlag(int baseFlag) {
            this.baseFlag = baseFlag;
        }
    }
}

