From 6c4a4e05c1afa1d7c7424207015b7b711e06150a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=96=87?= <3466561528@qq.com> Date: Thu, 23 Apr 2026 15:15:54 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=B5=8B=E8=AF=95=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E6=AD=A3=E5=B8=B8=EF=BC=8C=E4=BB=85=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E4=BA=86=E9=83=A8=E5=88=86=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../njcn/gather/icd/mapping/controller/MappingController.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/controller/MappingController.java b/tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/controller/MappingController.java index 7e21674..923d8eb 100644 --- a/tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/controller/MappingController.java +++ b/tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/controller/MappingController.java @@ -89,4 +89,6 @@ public class MappingController extends BaseController { GenerateMappingResult result = mappingTaskService.getIcdMmsJson(command); return responseConverter.fromSubmitResult(result); } + + //测试提交添加的注释内容 } From 98b3f0dbe8249dff3c85e285e76d85de1b22252a Mon Sep 17 00:00:00 2001 From: caizhouyu Date: Wed, 29 Apr 2026 14:23:01 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat(mms-mapping):=20=E6=B7=BB=E5=8A=A0ICD?= =?UTF-8?q?=E8=BD=ACXML=E6=98=A0=E5=B0=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增DefaultCfgToXml.txt模板文件,定义报告列表、逻辑节点分类、相别、倍数器、单位等配置项 - 添加IcdToXmlGenerateCommand类,封装ICD文件转换命令参数,包括文件名、字节流、版本号等属性 - 创建IcdToXmlGenerateRequest类,定义ICD转XML生成请求参数,包含版本号、作者、保存选项等字段 - 实现IcdToXmlGenerateResult类,封装转换结果,包含状态、消息、IED名称、LD实例等信息 - 开发IcdToXmlMappingService组件,提供索引映射配置和统计数据分析功能 - 添加IcdToXmlRequestConverter组件,实现请求参数到命令对象的转换逻辑 - 创建IcdToXmlResponse类,定义ICD转XML响应结构,包含状态、消息、映射文档等属性 - 实现IcdToXmlResponseConverter组件,将结果对象转换为响应对象 - 添加IcdToXmlTaskAppService服务,协调各个组件完成ICD到XML的完整转换流程 - 集成ICD解析、模板加载、索引分析、验证、映射生成等核心功能模块 --- .../component/IcdToXmlMappingService.java | 231 ++++ .../component/IcdToXmlRequestConverter.java | 78 ++ .../component/IcdToXmlResponseConverter.java | 62 + .../component/JsonToXmlConversionService.java | 1012 +++++++++++++++++ .../component/RuleBasedXmlMappingService.java | 852 ++++++++++++++ .../mapping/controller/MappingController.java | 40 + .../pojo/bo/IcdToXmlGenerateResult.java | 38 + .../pojo/dto/IcdToXmlGenerateCommand.java | 91 ++ .../pojo/param/IcdToXmlGenerateRequest.java | 76 ++ .../mapping/pojo/param/JsonToXmlRequest.java | 32 + .../icd/mapping/pojo/vo/IcdToXmlResponse.java | 36 + .../service/impl/IcdToXmlTaskAppService.java | 182 +++ .../icd/mapping/utils/XmlTemplateParser.java | 42 + .../resources/template/DefaultCfgToXml.txt | 723 ++++++++++++ .../resources/template/JiangSu_Config2.xml | 248 ++++ .../src/main/resources/template/默认规则.txt | 127 +++ 16 files changed, 3870 insertions(+) create mode 100644 tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/component/IcdToXmlMappingService.java create mode 100644 tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/component/IcdToXmlRequestConverter.java create mode 100644 tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/component/IcdToXmlResponseConverter.java create mode 100644 tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/component/JsonToXmlConversionService.java create mode 100644 tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/component/RuleBasedXmlMappingService.java create mode 100644 tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/pojo/bo/IcdToXmlGenerateResult.java create mode 100644 tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/pojo/dto/IcdToXmlGenerateCommand.java create mode 100644 tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/pojo/param/IcdToXmlGenerateRequest.java create mode 100644 tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/pojo/param/JsonToXmlRequest.java create mode 100644 tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/pojo/vo/IcdToXmlResponse.java create mode 100644 tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/service/impl/IcdToXmlTaskAppService.java create mode 100644 tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/utils/XmlTemplateParser.java create mode 100644 tools/mms-mapping/src/main/resources/template/DefaultCfgToXml.txt create mode 100644 tools/mms-mapping/src/main/resources/template/JiangSu_Config2.xml create mode 100644 tools/mms-mapping/src/main/resources/template/默认规则.txt diff --git a/tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/component/IcdToXmlMappingService.java b/tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/component/IcdToXmlMappingService.java new file mode 100644 index 0000000..0454d07 --- /dev/null +++ b/tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/component/IcdToXmlMappingService.java @@ -0,0 +1,231 @@ +package com.njcn.gather.icd.mapping.component; + + +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import org.springframework.beans.factory.annotation.Autowired; +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.util.List; +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; +@Setter +@Getter +@Component +public class IcdToXmlMappingService { + + private IndexMappingConfig indexMapping; + + @Data + public static class IndexMappingConfig { + private StatIndex mmxu; + private StatIndex mhai; + private StatIndex interHarmonic; + private StatIndex msqi; + private Integer mflkShort; + private Integer mflkLong; + private Integer qvvr; + + @Data + public static class StatIndex { + private Integer average; + private Integer maximum; + private Integer minimum; + private Integer percentile95; + } + } + + public IndexMappingConfig toIndexMapping(){ + IndexMappingConfig indexMapping = new IndexMappingConfig(); + return indexMapping; + } + + public void setIndexMapping(IndexMappingConfig config) { + this.indexMapping = config; + } + + public IndexMappingConfig buildIndexMappingFromSelection(List indexSelectionGroups) { + IndexMappingConfig config = new IndexMappingConfig(); + + if (indexSelectionGroups == null || indexSelectionGroups.isEmpty()) { + return config; + } + + for (IndexSelectionGroupCommand group : indexSelectionGroups) { + String groupKey = group.getGroupKey(); + List bindings = group.getBindings(); + + if (bindings == null || bindings.isEmpty()) { + continue; + } + + if ("统计数据__DSSTATISTICDATA".equals(groupKey)) { + processStatisticDataGroup(config, bindings); + } else if ("波动闪变__DSFLICKERDATA".equals(groupKey)) { + processFlickerDataGroup(config, bindings); + } else if ("暂态事件__DSEVEQVVR".equals(groupKey)) { + processQvvrGroup(config, bindings); + } + } + + return config; + } + + private void processStatisticDataGroup(IndexMappingConfig config, List bindings) { + for (IndexBindingCommand binding : bindings) { + String dataSetName = binding.getDataSetName(); + String label = binding.getLabel(); + Integer lnInst = parseLnInst(binding.getLnInst()); + + if (lnInst == null) { + continue; + } + + if ("dsStHarm".equals(dataSetName) ) { + if (config.getMhai() == null) { + config.setMhai(new IndexMappingConfig.StatIndex()); + } + mapStatIndex(config.getMhai(), label, lnInst); + } else if ("dsStIHarm".equals(dataSetName)) { + if (config.getInterHarmonic() == null) { + config.setInterHarmonic(new IndexMappingConfig.StatIndex()); + } + mapStatIndex(config.getInterHarmonic(), label, lnInst); + } else if ("dsStMMXU".equals(dataSetName)) { + if (config.getMmxu() == null) { + config.setMmxu(new IndexMappingConfig.StatIndex()); + } + mapStatIndex(config.getMmxu(), label, lnInst); + }else if ("dsStMSQI".equals(dataSetName)) { + if (config.getMsqi() == null) { + config.setMsqi(new IndexMappingConfig.StatIndex()); + } + mapStatIndex(config.getMsqi(), label, lnInst); + } else if ("dsStatisticData".equals(dataSetName)) { + if (label != null && label.contains("间谐波")) { + if (config.getInterHarmonic() == null) { + config.setInterHarmonic(new IndexMappingConfig.StatIndex()); + } + mapStatIndex(config.getInterHarmonic(), label, lnInst); + } else { + if (config.getMmxu() == null) { + config.setMmxu(new IndexMappingConfig.StatIndex()); + } + mapStatIndex(config.getMmxu(), label, lnInst); + if (config.getMhai() == null) { + config.setMhai(new IndexMappingConfig.StatIndex()); + } + mapStatIndex(config.getMhai(), label, lnInst); + if (config.getMsqi() == null) { + config.setMsqi(new IndexMappingConfig.StatIndex()); + } + mapStatIndex(config.getMsqi(), label, lnInst); + } + } + } + } + + private void processFlickerDataGroup(IndexMappingConfig config, List bindings) { + for (IndexBindingCommand binding : bindings) { + String dataSetName = binding.getDataSetName(); + String label = binding.getLabel(); + Integer lnInst = parseLnInst(binding.getLnInst()); + + if (lnInst == null) { + continue; + } + if ("dsPST".equals(dataSetName)) { + if (config.getMflkShort() == null) { + config.setMflkShort(0); + } + config.setMflkShort(lnInst); + } + else if ("dsPLT".equals(dataSetName)) { + if (config.getMflkLong() == null) { + config.setMflkLong(0); + } + config.setMflkLong(lnInst); + }else { + if (config.getMflkShort() == null) { + config.setMflkShort(0); + } + config.setMflkShort(lnInst); + if (config.getMflkLong() == null) { + config.setMflkLong(0); + } + config.setMflkLong(lnInst); + } + } + } + + private void processQvvrGroup(IndexMappingConfig config, List bindings) { + for (IndexBindingCommand binding : bindings) { + String label = binding.getLabel(); + Integer lnInst = parseLnInst(binding.getLnInst()); + + if (lnInst == null) { + continue; + } + + if (label != null && label.startsWith("电压变动")) { + config.setQvvr(lnInst); + } + } + } + + private void mapStatIndex(IndexMappingConfig.StatIndex statIndex, String label, Integer lnInst) { + if (label == null) { + return; + } + + switch (label) { + case "最大值": + statIndex.setMaximum(lnInst); + break; + case "最小值": + statIndex.setMinimum(lnInst); + break; + case "平均值": + statIndex.setAverage(lnInst); + break; + case "95值": + statIndex.setPercentile95(lnInst); + break; + case "间谐波最大值": + statIndex.setMaximum(lnInst); + break; + case "间谐波最小值": + statIndex.setMinimum(lnInst); + break; + case "间谐波平均值": + statIndex.setAverage(lnInst); + break; + case "间谐波95值": + statIndex.setPercentile95(lnInst); + break; + default: + break; + } + } + + private Integer parseLnInst(String lnInstStr) { + if (lnInstStr == null || lnInstStr.trim().isEmpty()) { + return null; + } + try { + return Integer.parseInt(lnInstStr.trim()); + } catch (NumberFormatException e) { + return null; + } + } + +} \ No newline at end of file diff --git a/tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/component/IcdToXmlRequestConverter.java b/tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/component/IcdToXmlRequestConverter.java new file mode 100644 index 0000000..82d06f0 --- /dev/null +++ b/tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/component/IcdToXmlRequestConverter.java @@ -0,0 +1,78 @@ +package com.njcn.gather.icd.mapping.component; + +import com.njcn.gather.icd.mapping.pojo.dto.IcdToXmlGenerateCommand; +import com.njcn.gather.icd.mapping.pojo.dto.IndexBindingCommand; +import com.njcn.gather.icd.mapping.pojo.dto.IndexSelectionGroupCommand; +import com.njcn.gather.icd.mapping.pojo.param.IcdToXmlGenerateRequest; +import com.njcn.gather.icd.mapping.pojo.param.IndexBindingRequest; +import com.njcn.gather.icd.mapping.pojo.param.IndexSelectionGroupRequest; +import com.njcn.gather.icd.mapping.pojo.param.JsonToXmlRequest;import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +@Component +public class IcdToXmlRequestConverter { + + public IcdToXmlGenerateCommand toCommand(MultipartFile icdFile, IcdToXmlGenerateRequest request) { + IcdToXmlGenerateCommand command = new IcdToXmlGenerateCommand(); + try { + command.setFileBytes(icdFile.getBytes()); + } catch (IOException e) { + throw new RuntimeException("读取 ICD 文件失败", e); + } + command.setFileName(icdFile.getOriginalFilename()); + command.setVersion(request.getVersion()); + command.setAuthor(request.getAuthor()); + command.setSaveToDisk(request.isSaveToDisk()); + command.setOutputDir(request.getOutputDir()); + command.setIndexSelection(toIndexSelectionGroupCommands(request.getIndexSelection())); + return command; + } + + /** + * 将 JsonToXmlRequest 转换为 IcdToXmlGenerateCommand。 + * 注意:此方法不处理文件,仅转换索引选择结果。 + */ + public IcdToXmlGenerateCommand toCommand(JsonToXmlRequest request) { + IcdToXmlGenerateCommand command = new IcdToXmlGenerateCommand(); + command.setVersion("1.0"); + command.setAuthor(""); + command.setSaveToDisk(false); + command.setOutputDir(null); + + + return command; + } + + private List toIndexSelectionGroupCommands(List indexSelection) { + List indexSelectionGroupCommands = new ArrayList<>(); + if (indexSelection != null) { + for (IndexSelectionGroupRequest groupRequest : indexSelection) { + IndexSelectionGroupCommand groupCommand = new IndexSelectionGroupCommand(); + groupCommand.setGroupKey(groupRequest.getGroupKey()); + groupCommand.setGroupDesc(groupRequest.getGroupDesc()); + groupCommand.setBindings(toIndexBindingCommands(groupRequest.getBindings())); + indexSelectionGroupCommands.add(groupCommand); + } + } + return indexSelectionGroupCommands; + } + + private List toIndexBindingCommands(List bindings) { + List indexBindingCommands = new ArrayList<>(); + if (bindings != null) { + for (IndexBindingRequest bindingRequest : bindings) { + IndexBindingCommand bindingCommand = new IndexBindingCommand(); + bindingCommand.setReportName(bindingRequest.getReportName()); + bindingCommand.setDataSetName(bindingRequest.getDataSetName()); + bindingCommand.setLabel(bindingRequest.getLabel()); + bindingCommand.setLnInst(bindingRequest.getLnInst()); + indexBindingCommands.add(bindingCommand); + } + } + return indexBindingCommands; + } +} \ No newline at end of file diff --git a/tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/component/IcdToXmlResponseConverter.java b/tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/component/IcdToXmlResponseConverter.java new file mode 100644 index 0000000..c0140b7 --- /dev/null +++ b/tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/component/IcdToXmlResponseConverter.java @@ -0,0 +1,62 @@ +package com.njcn.gather.icd.mapping.component; + +import com.njcn.gather.icd.mapping.pojo.bo.IcdToXmlGenerateResult; +import com.njcn.gather.icd.mapping.pojo.bo.analysis.IndexCandidate; +import com.njcn.gather.icd.mapping.pojo.bo.analysis.IndexCandidateReportItem; +import com.njcn.gather.icd.mapping.pojo.vo.IcdToXmlResponse; +import com.njcn.gather.icd.mapping.pojo.vo.IndexCandidateReportItemResponse; +import com.njcn.gather.icd.mapping.pojo.vo.IndexCandidateResponse; +import com.njcn.gather.icd.mapping.pojo.vo.MappingDocumentResponse; +import org.springframework.stereotype.Component; + +@Component +public class IcdToXmlResponseConverter { + + public IcdToXmlResponse fromResult(IcdToXmlGenerateResult result) { + IcdToXmlResponse response = new IcdToXmlResponse(); + response.setStatus(result.getStatus()); + response.setMessage(result.getMessage()); + response.setIedName(result.getIedName()); + response.setLdInst(result.getLdInst()); + response.setSavedPath(result.getSavedPath()); + response.getProblems().addAll(result.getProblems()); + + if (result.getIndexAnalysis() != null && result.getIndexAnalysis().getCandidates() != null) { + for (IndexCandidate candidate : result.getIndexAnalysis().getCandidates()) { + IndexCandidateResponse candidateResponse = new IndexCandidateResponse(); + candidateResponse.setGroupKey(candidate.getGroupKey()); + candidateResponse.setGroupDesc(candidate.getGroupDesc()); + candidateResponse.setReportCount(candidate.getReportCount()); + candidateResponse.getTemplateLabels().addAll(candidate.getTemplateLabels()); + + if (candidate.getReports() != null) { + for (IndexCandidateReportItem item : candidate.getReports()) { + IndexCandidateReportItemResponse itemResponse = new IndexCandidateReportItemResponse(); + itemResponse.setReportName(item.getReportName()); + itemResponse.setDataSetName(item.getDataSetName()); + itemResponse.setReportDesc(item.getReportDesc()); + itemResponse.getAvailableLnInstValues().addAll(item.getAvailableLnInstValues()); + candidateResponse.getReports().add(itemResponse); + } + } + + response.getIndexCandidates().add(candidateResponse); + } + } + + if (result.getMappingDocument() != null) { + MappingDocumentResponse doc = new MappingDocumentResponse(); + doc.setVersion(result.getMappingDocument().getVersion()); + doc.setAuthor(result.getMappingDocument().getAuthor()); + doc.setIed(result.getMappingDocument().getIed()); + doc.setLd(result.getMappingDocument().getLd()); + doc.setReportCount(result.getMappingDocument().getReportMap() == null + ? 0 : result.getMappingDocument().getReportMap().size()); + doc.setDataSetCount(result.getMappingDocument().getDataSetList() == null + ? 0 : result.getMappingDocument().getDataSetList().size()); + response.setMappingDocument(doc); + } + + return response; + } +} \ No newline at end of file diff --git a/tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/component/JsonToXmlConversionService.java b/tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/component/JsonToXmlConversionService.java new file mode 100644 index 0000000..8395005 --- /dev/null +++ b/tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/component/JsonToXmlConversionService.java @@ -0,0 +1,1012 @@ +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 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.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 索引映射配置 + * @return 生成的XML文件路径 + * @throws Exception 转换异常 + */ + public String convertFromJson(String mappingJson, + InputStream templateStream, + List ruleStreams, + IcdToXmlMappingService.IndexMappingConfig indexMapping) throws Exception { + + // 1. 反序列化JSON为MappingDocument对象 + MappingDocument mappingDocument = objectMapper.readValue(mappingJson, MappingDocument.class); + + // 2. 使用现有的规则引擎生成XML + // 注意:这里复用RuleBasedXmlMappingService的核心逻辑 + // 但数据来源从ICD直接解析改为从MappingDocument提取 + String xmlContent = buildXmlFromMapping(mappingDocument, templateStream, ruleStreams, indexMapping); + + // 3. 保存为临时文件 + Path tempPath = Files.createTempFile("converted_", ".xml"); + Files.write(tempPath, xmlContent.getBytes(StandardCharsets.UTF_8)); + + return tempPath.toString(); + } + + /** + * 从MappingDocument构建XML内容 + */ + private String buildXmlFromMapping(MappingDocument mappingDocument, + InputStream templateStream, + List ruleStreams, + IcdToXmlMappingService.IndexMappingConfig indexMapping) throws Exception { + + String templateContent = readInputStreamToString(templateStream); + + String xmlContent = fillIedInfo(templateContent, mappingDocument); + + xmlContent = fillReportControlsFromMapping(xmlContent, mappingDocument); + + xmlContent = applyRulesFromMapping(xmlContent, mappingDocument, ruleStreams, indexMapping); + + 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(); + + if (iedName != null && !iedName.isEmpty()) { + xmlContent = xmlContent.replaceAll( + "\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\n"); + } + } + } + + reportStatBuilder.append("\t\t"); + + xmlContent = xmlContent.replaceAll( + "[\\s\\S]*?", + 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("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(",3"); + + if(rc.getName().contains("PLT") || rc.getName().contains("Flicker")){ + sb.append(",1"); + }else if(rc.getName().contains("PST") || rc.getName().contains("Fluc")){ + sb.append(",2"); + } else { + sb.append(",0"); + } + + return sb.toString(); + } + + /** + * 从MappingDocument应用规则 + */ + private String applyRulesFromMapping(String xmlContent, + MappingDocument mappingDocument, + List ruleStreams, + IcdToXmlMappingService.IndexMappingConfig indexMapping) throws Exception { + + var mergedRules = mergeAllRulesDesc(ruleStreams, indexMapping); + + var mappingMetrics = extractMetricsFromMapping(mappingDocument); + + System.out.println("========== 开始从JSON匹配规则 =========="); + System.out.println("规则总数: " + mergedRules.size()); + System.out.println("JSON中指标总数: " + mappingMetrics.size()); + + var applicableRules = findApplicableRulesDesc(mergedRules, mappingMetrics); + + System.out.println("匹配成功: " + applicableRules.size() + " 条规则"); + System.out.println("匹配失败: " + (mergedRules.size() - applicableRules.size()) + " 条规则"); + System.out.println("========== JSON规则匹配结束 ==========\n"); + + return applyRulesToXml(xmlContent, applicableRules); + } + + /** + * 合并所有规则文件 + */ + private java.util.Map> mergeAllRules( + List ruleStreams, + IcdToXmlMappingService.IndexMappingConfig indexMapping) throws Exception { + + java.util.Map> mergedRules = new java.util.LinkedHashMap<>(); + + for (InputStream ruleStream : ruleStreams) { + var rules = parseRuleFile(ruleStream, indexMapping); + for (var entry : rules.entrySet()) { + String key = entry.getKey(); + List ruleList = entry.getValue(); + mergedRules.computeIfAbsent(key, k -> new ArrayList<>()).addAll(ruleList); + } + } + + return mergedRules; + } + + private java.util.Map> mergeAllRulesDesc( + List ruleStreams, + IcdToXmlMappingService.IndexMappingConfig indexMapping) throws Exception { + + java.util.Map> mergedRules = new java.util.LinkedHashMap<>(); + + for (InputStream ruleStream : ruleStreams) { + var rules = parseRuleFileDesc(ruleStream, indexMapping); + for (var entry : rules.entrySet()) { + String key = entry.getKey(); + List ruleList = entry.getValue(); + mergedRules.computeIfAbsent(key, k -> new ArrayList<>()).addAll(ruleList); + } + } + + return mergedRules; + } + + /** + * 解析规则文件 + */ + private java.util.Map> parseRuleFile( + InputStream ruleStream, + IcdToXmlMappingService.IndexMappingConfig indexMapping) throws Exception { + + java.util.Map> 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( + "", java.util.regex.Pattern.CASE_INSENSITIVE + ); + + while ((line = reader.readLine()) != null) { + line = line.trim(); + + if (line.startsWith(" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tools/mms-mapping/src/main/resources/template/默认规则.txt b/tools/mms-mapping/src/main/resources/template/默认规则.txt new file mode 100644 index 0000000..3a8e567 --- /dev/null +++ b/tools/mms-mapping/src/main/resources/template/默认规则.txt @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file