Compare commits
5 Commits
76a254fef4
...
2026-04
| Author | SHA1 | Date | |
|---|---|---|---|
| 2c1d926261 | |||
| 34b1a81c70 | |||
| 81e4ff4009 | |||
| f57fd45b47 | |||
| f69eed857f |
@@ -26,6 +26,7 @@ CN_Tool 是一个基于 Spring Boot 的多模块后端聚合工程,当前仓
|
||||
其中 `tools` 当前包含:
|
||||
|
||||
- `activate-tool`
|
||||
- `add-data`
|
||||
- `mms-mapping`
|
||||
- `wave-tool`
|
||||
|
||||
@@ -35,7 +36,7 @@ CN_Tool 是一个基于 Spring Boot 的多模块后端聚合工程,当前仓
|
||||
|
||||
- `entrance/src/main/java/com/njcn/gather/EntranceApplication.java`
|
||||
|
||||
`entrance` 模块聚合了 `system`、`disk-monitor`、`user`、`detection`、`activate-tool`、`wave-tool`、`mms-mapping`,是当前运行时主入口。
|
||||
`entrance` 模块聚合了 `system`、`disk-monitor`、`user`、`detection`、`activate-tool`、`add-data`、`wave-tool`、`mms-mapping`,是当前运行时主入口。
|
||||
|
||||
## 技术基线
|
||||
|
||||
@@ -82,6 +83,8 @@ P0 已补齐基线文档,建议按以下顺序阅读:
|
||||
- 当前以通信基础设施为主,包含 WebSocket / Netty 相关组件
|
||||
- `tools/activate-tool`
|
||||
- 负责激活码生成、激活码验证、许可证读取等能力
|
||||
- `tools/add-data`
|
||||
- 当前提供电能质量 13 张表批量补数、任务状态查询和模板规则查询能力
|
||||
- `tools/mms-mapping`
|
||||
- 负责 ICD 文件解析与 MMS 映射数据生成能力
|
||||
- `tools/wave-tool`
|
||||
|
||||
@@ -7,22 +7,36 @@
|
||||
当前真实保留的子模块有:
|
||||
|
||||
- `activate-tool`
|
||||
- `add-data`
|
||||
- `mms-mapping`
|
||||
- `wave-tool`
|
||||
|
||||
因此,`tools` 现阶段仍然是聚合模块,但当前已实际承载激活工具、ICD/MMS 映射工具和波形查看工具三个子模块。
|
||||
因此,`tools` 现阶段仍然是聚合模块,但当前已实际承载激活工具、电能质量数据补录工具、ICD/MMS 映射工具和波形查看工具四个子模块。
|
||||
|
||||
## 当前结构
|
||||
|
||||
```text
|
||||
tools/
|
||||
├── activate-tool/
|
||||
├── add-data/
|
||||
├── mms-mapping/
|
||||
└── wave-tool/
|
||||
```
|
||||
|
||||
其中 `tools/mms-mapping` 当前 Maven `artifactId` 为 `mms-mapping`。
|
||||
|
||||
## add-data 的职责
|
||||
|
||||
`add-data` 当前已提供电能质量数据批量补录能力,包含:
|
||||
|
||||
- 任务预估接口
|
||||
- 任务创建接口
|
||||
- 任务状态查询接口
|
||||
- 模板规则查询接口
|
||||
- 异步执行、批量写入和内存态任务状态管理
|
||||
|
||||
模块内部已按职责拆分 `controller`、`service`、`service/impl`、`component`、`pojo`、`config` 和 `util`,并通过 `JdbcTemplate + INSERT IGNORE` 执行批量补数。
|
||||
|
||||
## activate-tool 的职责
|
||||
|
||||
`activate-tool` 当前提供的能力主要围绕设备授权与许可证:
|
||||
@@ -76,7 +90,7 @@ tools/
|
||||
|
||||
## 依赖关系
|
||||
|
||||
`tools/activate-tool`、`tools/mms-mapping` 与 `tools/wave-tool` 当前主要依赖:
|
||||
`tools/activate-tool`、`tools/add-data`、`tools/mms-mapping` 与 `tools/wave-tool` 当前主要依赖:
|
||||
|
||||
- `com.njcn:njcn-common`
|
||||
- `com.njcn:spingboot2.3.12`
|
||||
|
||||
55
tools/add-data/README.md
Normal file
55
tools/add-data/README.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# add-data 模块说明
|
||||
|
||||
## 模块定位
|
||||
|
||||
`add-data` 当前提供电能质量 13 张表批量补数能力,支持补数规模预估、后台异步执行、任务状态查询和前端模板规则查询。
|
||||
|
||||
## 当前范围
|
||||
|
||||
当前模块本次实现范围聚焦在工具型批处理,不接入以下内容:
|
||||
|
||||
- 覆盖更新或先删后写
|
||||
- 监测点基础信息管理
|
||||
- 独立任务持久化表
|
||||
- 前端页面代码
|
||||
|
||||
目录中保留历史 SQL 脚本 `DATA_FLICKER.sql`,并同步复制到 `src/main/resources/sql/add-data` 供运行时解析表字段元数据。
|
||||
|
||||
## 当前结构
|
||||
|
||||
```text
|
||||
add-data/
|
||||
├── pom.xml
|
||||
├── README.md
|
||||
├── DATA_FLICKER.sql
|
||||
└── src/main/java/com/njcn/gather/tool/adddata/
|
||||
├── component/
|
||||
├── config/
|
||||
├── controller/
|
||||
├── pojo/
|
||||
├── service/
|
||||
└── util/
|
||||
```
|
||||
|
||||
## 基础骨架说明
|
||||
|
||||
- `controller/AddDataTaskController`
|
||||
- 提供预估、创建任务、查询任务状态三个接口
|
||||
- `controller/AddDataTemplateController`
|
||||
- 提供前端参数模板规则查询接口
|
||||
- `component/AddDataTaskExecutor`
|
||||
- 负责后台异步补数任务执行
|
||||
- `component/AddDataBatchWriter`
|
||||
- 负责 `INSERT IGNORE` 批量写入与失败降级
|
||||
- `component/AddDataValueGenerator`
|
||||
- 负责按同源规则生成 13 张表数据
|
||||
- `component/AddDataTableRegistry`
|
||||
- 负责从 SQL 资源解析字段元数据并注册表定义
|
||||
- `component/AddDataTaskStatusHolder`
|
||||
- 首版以内存方式保存任务状态
|
||||
|
||||
## 扩展约束
|
||||
|
||||
当前实现按 `A/B/C/T` 四类数据类型生成和预估补数。
|
||||
|
||||
后续如果补齐逐表真实相别映射、任务持久化或更细粒度模板规则,应优先沿现有职责边界扩展,不回退为单一大类承载全部逻辑。
|
||||
@@ -1,371 +0,0 @@
|
||||
# getIcdMmsJson 标准 API 调试文档
|
||||
|
||||
## 1. 文档范围
|
||||
|
||||
本文档用于说明 `mms-mapping` 模块统一调试接口 `getIcdMmsJson` 的标准调用方式、请求结构、响应规则和联调注意事项。
|
||||
|
||||
本文档内容以当前源码为准,主要对照以下实现:
|
||||
|
||||
- `tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/controller/MappingController.java`
|
||||
- `tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/component/MappingRequestConverter.java`
|
||||
- `tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/component/MappingResponseConverter.java`
|
||||
- `tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/service/impl/MappingTaskServiceImpl.java`
|
||||
- `tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/component/MappingGenerationService.java`
|
||||
- `tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/pojo/param/GenerateMappingFromIcdRequest.java`
|
||||
- `tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/pojo/vo/MappingTaskResponse.java`
|
||||
|
||||
说明:
|
||||
|
||||
- 本文档仅描述接口契约和调试方式,不改动业务代码。
|
||||
- 本次未执行 `mvn` 编译、打包或真实接口联调。
|
||||
- 如文档与运行结果冲突,以源码和实际部署配置为准。
|
||||
|
||||
## 2. 接口基本信息
|
||||
|
||||
| 项 | 说明 |
|
||||
| --- | --- |
|
||||
| 接口名称 | `getIcdMmsJson` |
|
||||
| 请求方法 | `POST` |
|
||||
| 请求路径 | `/api/mms-mapping/get-icd-mms-json` |
|
||||
| Content-Type | `multipart/form-data` |
|
||||
| 控制器入口 | `MappingController#getIcdMmsJson` |
|
||||
| 请求组成 | `icdFile` 文件 Part + `request` JSON Part |
|
||||
| 正常业务响应体 | `MappingTaskResponse` |
|
||||
|
||||
## 3. 接口职责
|
||||
|
||||
该接口是 `mms-mapping` 模块的统一调试入口,串联以下两个阶段:
|
||||
|
||||
1. 上传 ICD 文件并完成解析,生成 `icdDocument` 和 `indexCandidates`
|
||||
2. 根据 `request.indexSelection` 判断是否继续生成正式 `mappingJson`
|
||||
|
||||
接口行为分为三种典型结果:
|
||||
|
||||
1. `request.indexSelection` 未传或为空
|
||||
返回 `NEED_INDEX_SELECTION`,用于引导前端或调试人员先确认标签与 `lnInst` 的绑定关系。
|
||||
2. `request.indexSelection` 已传但校验不通过
|
||||
返回 `NEED_INDEX_SELECTION`,同时通过 `problems` 给出不合法原因,要求重新选择。
|
||||
3. `request.indexSelection` 校验通过
|
||||
返回 `SUCCESS`,输出正式 `mappingJson`,必要时同时落盘并返回 `savedPath`。
|
||||
|
||||
补充说明:
|
||||
|
||||
- 该接口每次都会重新解析上传的 ICD 文件,因此第二次调试仍然必须重新上传 ICD 文件。
|
||||
- 该接口正常进入业务编排后,返回体类型为 `MappingTaskResponse`。
|
||||
- 如果异常发生在控制器参数绑定或请求转换阶段,例如文件为空、Part 缺失、JSON Part 解析失败,则由全局异常处理器统一包装为 `HttpResult<String>`,而不是 `MappingTaskResponse`。
|
||||
|
||||
## 4. 请求规范
|
||||
|
||||
### 4.1 multipart/form-data Part 说明
|
||||
|
||||
| Part 名称 | 类型 | 必填 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `icdFile` | File | 是 | ICD 文件,不能为空 |
|
||||
| `request` | JSON Part | 是 | 生成参数,必须按 `application/json` 发送 |
|
||||
|
||||
说明:
|
||||
|
||||
- `request` Part 不能省略。即使第一次只想拿候选结果,也必须传一个最小 JSON。
|
||||
- `request.indexSelection` 可以省略或传空数组,此时接口只返回候选结果,不生成正式映射。
|
||||
|
||||
### 4.2 request JSON 结构
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "2026-04-22",
|
||||
"author": "debug-user",
|
||||
"saveToDisk": false,
|
||||
"prettyJson": true,
|
||||
"outputDir": "D:/temp/mms-output",
|
||||
"indexSelection": [
|
||||
{
|
||||
"groupKey": "harm",
|
||||
"groupDesc": "谐波数据",
|
||||
"bindings": [
|
||||
{
|
||||
"reportName": "brcbStHarm",
|
||||
"dataSetName": "dsStHarm",
|
||||
"label": "A相",
|
||||
"lnInst": "1"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 request 字段说明
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `version` | String | 否 | 输出版本号。未传或空白时,后端按当天日期补齐,格式为 `yyyy-MM-dd` |
|
||||
| `author` | String | 否 | 作者。未传或空白时,回退到配置项 `icd.mapping.default-author`,默认值为 `system` |
|
||||
| `saveToDisk` | boolean | 否 | 是否将生成结果写入磁盘 |
|
||||
| `prettyJson` | boolean | 否 | 是否输出格式化 JSON。`true` 为美化 JSON,`false` 为紧凑 JSON |
|
||||
| `outputDir` | String | 否 | 输出目录。未传或空白时,先回退到配置项 `icd.mapping.default-output-dir`;如果配置也为空,最终落到当前工作目录 |
|
||||
| `indexSelection` | Array | 否 | 标签与 `lnInst` 的最终绑定关系。未传或为空时,只返回候选结果 |
|
||||
|
||||
### 4.4 indexSelection 字段说明
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `groupKey` | String | 是 | 分组唯一键,必须使用第一次响应里返回的原值 |
|
||||
| `groupDesc` | String | 否 | 分组中文描述,便于调试查看 |
|
||||
| `bindings` | Array | 是 | 当前业务分组下最终确认的绑定关系列表 |
|
||||
|
||||
### 4.5 bindings 字段说明
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `reportName` | String | 是 | 绑定发生在哪个报告上,例如 `brcbStHarm` |
|
||||
| `dataSetName` | String | 是 | 绑定发生在哪个数据集上,例如 `dsStHarm` |
|
||||
| `label` | String | 是 | 业务标签,例如 `A相`、`最大值`、`实时数据` |
|
||||
| `lnInst` | String | 是 | 标签最终绑定到的逻辑节点实例值,例如 `1`、`2`、`3` |
|
||||
|
||||
## 5. 标准调试流程
|
||||
|
||||
### 5.1 第一次调试:只获取候选结果
|
||||
|
||||
用途:
|
||||
|
||||
- 上传 ICD 文件
|
||||
- 获取 `icdDocument`
|
||||
- 获取 `indexCandidates`
|
||||
- 确认每个业务分组下可选的 `reportName`、`dataSetName` 和 `availableLnInstValues`
|
||||
|
||||
调用要求:
|
||||
|
||||
- `request` Part 仍然必须传
|
||||
- `request.indexSelection` 可以不传,或传空数组
|
||||
|
||||
预期结果:
|
||||
|
||||
- `status = NEED_INDEX_SELECTION`
|
||||
- 响应中返回 `icdDocument`
|
||||
- 响应中返回 `indexCandidates`
|
||||
|
||||
### 5.2 第二次调试:带索引绑定生成正式结果
|
||||
|
||||
用途:
|
||||
|
||||
- 根据第一次返回的 `indexCandidates` 组装 `request.indexSelection`
|
||||
- 再次上传同一个 ICD 文件
|
||||
- 生成正式 `mappingJson`
|
||||
|
||||
调用要求:
|
||||
|
||||
- 必须继续上传 `icdFile`
|
||||
- `groupKey` 必须沿用第一次返回值
|
||||
- `reportName`、`dataSetName`、`lnInst` 必须与第一次返回的候选结果匹配
|
||||
|
||||
预期结果:
|
||||
|
||||
- `status = SUCCESS`
|
||||
- 响应中返回 `mappingJson`
|
||||
- 当 `saveToDisk = true` 时,响应中额外返回 `savedPath`
|
||||
|
||||
### 5.3 第二次调试但绑定不合法
|
||||
|
||||
适用场景:
|
||||
|
||||
- `groupKey` 与候选结果不匹配
|
||||
- `reportName` 或 `dataSetName` 不在候选集中
|
||||
- `lnInst` 不在 `availableLnInstValues` 内
|
||||
- 绑定关系缺失、不完整或结构错误
|
||||
|
||||
预期结果:
|
||||
|
||||
- `status = NEED_INDEX_SELECTION`
|
||||
- 响应中仍然返回 `icdDocument` 和 `indexCandidates`
|
||||
- `problems` 返回具体问题列表,要求重新确认绑定关系
|
||||
|
||||
## 6. 响应规范
|
||||
|
||||
### 6.1 正常业务响应体
|
||||
|
||||
接口正常进入业务编排后,统一返回 `MappingTaskResponse`。该对象使用了 `@JsonInclude(JsonInclude.Include.NON_EMPTY)`,空字段和空集合不会参与序列化。
|
||||
|
||||
基础字段说明:
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `status` | Enum | 本次处理状态,可能为 `SUCCESS`、`NEED_INDEX_SELECTION`、`FAILED` |
|
||||
| `message` | String | 状态说明或错误提示 |
|
||||
| `icdDocument` | Object | 需要重新选择索引时返回的 ICD 解析结果 |
|
||||
| `mappingJson` | String | 正式生成成功后的映射 JSON 文本 |
|
||||
| `savedPath` | String | 结果已落盘时返回的绝对路径 |
|
||||
| `indexCandidates` | Array | 待绑定状态下返回的索引候选分组 |
|
||||
| `problems` | Array | 模板校验、候选分析或绑定校验问题 |
|
||||
|
||||
字段出现规则:
|
||||
|
||||
| 状态 | 必有字段 | 可能出现字段 |
|
||||
| --- | --- | --- |
|
||||
| `SUCCESS` | `status`、`message`、`mappingJson` | `savedPath`、`problems` |
|
||||
| `NEED_INDEX_SELECTION` | `status`、`message`、`icdDocument`、`indexCandidates` | `problems` |
|
||||
| `FAILED` | `status`、`message` | `problems` |
|
||||
|
||||
### 6.2 NEED_INDEX_SELECTION 响应示例
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "NEED_INDEX_SELECTION",
|
||||
"message": "索引配置缺失,请根据候选信息完成标签与数字索引的绑定后重新提交",
|
||||
"icdDocument": {
|
||||
"fileName": "demo.icd",
|
||||
"iedName": "IED1",
|
||||
"ldInst": "LD0",
|
||||
"ldPrefix": "LD",
|
||||
"logicalNodes": [
|
||||
{
|
||||
"lnInst": "1"
|
||||
}
|
||||
]
|
||||
},
|
||||
"indexCandidates": [
|
||||
{
|
||||
"groupKey": "harm",
|
||||
"groupDesc": "谐波数据",
|
||||
"reportCount": 1,
|
||||
"templateLabels": [
|
||||
"A相",
|
||||
"B相",
|
||||
"C相"
|
||||
],
|
||||
"reports": [
|
||||
{
|
||||
"reportName": "brcbStHarm",
|
||||
"dataSetName": "dsStHarm",
|
||||
"reportDesc": "谐波报告",
|
||||
"availableLnInstValues": [
|
||||
"1",
|
||||
"2",
|
||||
"3"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- `icdDocument` 实际字段可能比示例更多。
|
||||
- 如果本次是“索引配置不合法”而不是“索引配置缺失”,通常还会返回 `problems`。
|
||||
|
||||
### 6.3 SUCCESS 响应示例
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "SUCCESS",
|
||||
"message": "映射生成成功",
|
||||
"mappingJson": "{\n \"version\": \"2026-04-22\",\n \"author\": \"debug-user\",\n \"ied\": \"IED1\",\n \"ld\": \"LD\",\n \"instList\": []\n}"
|
||||
}
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- `mappingJson` 是字符串字段,字段值本身是一段 JSON 文本。
|
||||
- 当 `saveToDisk = true` 时,响应中还会额外返回 `savedPath`。
|
||||
|
||||
### 6.4 FAILED 响应示例
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "FAILED",
|
||||
"message": "映射生成失败:加载 DefaultCfg.txt 失败:默认模板文件不存在:template/DefaultCfg.txt",
|
||||
"problems": [
|
||||
"加载 DefaultCfg.txt 失败:默认模板文件不存在:template/DefaultCfg.txt"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- `FAILED` 主要对应服务编排阶段捕获到的运行异常,例如 ICD 解析、模板加载、映射生成、序列化或落盘失败。
|
||||
- 并非所有错误都会进入 `FAILED`。如果异常发生在控制器参数绑定或请求转换阶段,会走全局异常处理器,而不是这里的业务响应结构。
|
||||
|
||||
## 7. 全局异常响应说明
|
||||
|
||||
以下场景通常不会返回 `MappingTaskResponse`,而是由 `GlobalBusinessExceptionHandler` 统一包装:
|
||||
|
||||
- `icdFile` 缺失或为空
|
||||
- `request` Part 缺失
|
||||
- `request` Part 的 `Content-Type` 不是 `application/json`
|
||||
- `multipart/form-data` 结构不合法
|
||||
- JSON 反序列化失败或框架参数绑定失败
|
||||
|
||||
这类异常最终会包装为统一的 `HttpResult<String>` 响应,具体字段结构以全局公共响应定义为准,本文不展开其完整协议,只强调:
|
||||
|
||||
- 不能把这类错误等同理解为 `MappingTaskResponse.status = FAILED`
|
||||
- 联调时应先区分“业务响应体”与“全局异常包装”
|
||||
|
||||
## 8. 调试示例
|
||||
|
||||
### 8.1 curl 示例:第一次调用,只获取候选结果
|
||||
|
||||
```powershell
|
||||
curl.exe -X POST "http://localhost:8080/api/mms-mapping/get-icd-mms-json" `
|
||||
-H "Accept: application/json" `
|
||||
-F 'icdFile=@D:/data/demo.icd' `
|
||||
-F 'request={"prettyJson":true,"saveToDisk":false};type=application/json'
|
||||
```
|
||||
|
||||
### 8.2 curl 示例:第二次调用,带索引绑定直接生成 MMS JSON
|
||||
|
||||
```powershell
|
||||
curl.exe -X POST "http://localhost:8080/api/mms-mapping/get-icd-mms-json" `
|
||||
-H "Accept: application/json" `
|
||||
-F 'icdFile=@D:/data/demo.icd' `
|
||||
-F 'request={"version":"2026-04-22","author":"debug-user","prettyJson":true,"saveToDisk":false,"indexSelection":[{"groupKey":"harm","groupDesc":"谐波数据","bindings":[{"reportName":"brcbStHarm","dataSetName":"dsStHarm","label":"A相","lnInst":"1"},{"reportName":"brcbStHarm","dataSetName":"dsStHarm","label":"B相","lnInst":"2"},{"reportName":"brcbStHarm","dataSetName":"dsStHarm","label":"C相","lnInst":"3"}]}]};type=application/json'
|
||||
```
|
||||
|
||||
## 9. Postman 调试要点
|
||||
|
||||
1. `Body` 选择 `form-data`
|
||||
2. `icdFile` 类型选择 `File`
|
||||
3. `request` 保持文本输入,但该 Part 的 `Content-Type` 必须显式设置为 `application/json`
|
||||
4. 第一次调试不要省略 `request` Part,只是不传 `indexSelection`
|
||||
5. 第二次调试时必须继续上传 ICD 文件,并严格按第一次返回的候选结果组装绑定关系
|
||||
|
||||
## 10. 常见问题
|
||||
|
||||
### 10.1 为什么第一次调试也必须传 `request`
|
||||
|
||||
因为控制器方法签名使用的是 `@RequestPart("request") GenerateMappingFromIcdRequest request`,该 Part 本身就是必填参数。第一次调试可以只传最小 JSON,但不能完全省略。
|
||||
|
||||
### 10.2 为什么没有传 `indexSelection`,却没有返回 `FAILED`
|
||||
|
||||
这是接口设计的正常行为。`indexSelection` 缺失或为空时,业务语义不是“接口执行失败”,而是“还需要前端继续确认索引绑定”,因此返回的是 `NEED_INDEX_SELECTION`。
|
||||
|
||||
### 10.3 `saveToDisk=true` 但没有传 `outputDir`,结果会保存到哪里
|
||||
|
||||
处理顺序如下:
|
||||
|
||||
1. 先读取请求中的 `outputDir`
|
||||
2. 如果请求空白,则回退到配置项 `icd.mapping.default-output-dir`
|
||||
3. 如果配置项也为空,则最终落到当前工作目录
|
||||
|
||||
### 10.4 `version` 不传时会变成什么
|
||||
|
||||
后端在正式生成映射文档时,会把空白 `version` 自动补成当天日期,格式为 `yyyy-MM-dd`。
|
||||
|
||||
### 10.5 `mappingJson` 为什么是字符串,不是嵌套对象
|
||||
|
||||
因为当前响应结构中 `mappingJson` 定义为 `String`,接口返回的是一段已经序列化好的 JSON 文本,而不是再次展开后的对象结构。
|
||||
|
||||
### 10.6 什么情况下会返回 `problems`
|
||||
|
||||
`problems` 主要用于承载以下问题:
|
||||
|
||||
- 默认模板校验问题
|
||||
- 索引候选分析问题
|
||||
- `indexSelection` 绑定校验问题
|
||||
- 服务编排阶段捕获到的异常原因
|
||||
|
||||
## 11. 当前边界
|
||||
|
||||
- 当前文档仅覆盖 `getIcdMmsJson` 接口,不覆盖 `get-icd` 与 `get-mms-json` 的独立接口文档
|
||||
- 当前文档重点描述业务返回体与调试方式,不展开全局 `HttpResult` 的完整协议
|
||||
- 示例中的 `icdDocument`、`indexCandidates` 和 `mappingJson` 为结构化示意,实际字段数量与内容以运行结果为准
|
||||
@@ -2,6 +2,12 @@
|
||||
|
||||
`mms-mapping` 模块负责解析 ICD 文件并生成 MMS 映射数据。当前统一调试入口为 `getIcdMmsJson`,该接口同时覆盖“先解析 ICD 获取索引候选”和“确认索引后生成正式 MMS JSON”两类场景。
|
||||
|
||||
## 0. 调试文档
|
||||
|
||||
- `getIcdMmsJson`:`API-getIcdMmsJson.md`
|
||||
- `getXmlFromJson`:`API-getXmlFromJson.md`
|
||||
- `buildIndexConfirmData` / `buildIndexSelection`:`API-buildIndexDebug.md`
|
||||
|
||||
## 1. 接口信息
|
||||
|
||||
- 路径:`POST /api/mms-mapping/get-icd-mms-json`
|
||||
|
||||
@@ -7,18 +7,26 @@ 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 com.njcn.gather.icd.mapping.pojo.vo.XmlFileResponse;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class IcdToXmlResponseConverter {
|
||||
|
||||
/** 默认 XML 展示文件名。 */
|
||||
private static final String DEFAULT_XML_FILE_NAME = "mapping.xml";
|
||||
/** XML 内容类型。 */
|
||||
private static final String XML_CONTENT_TYPE = "application/xml";
|
||||
/** XML 文件编码。 */
|
||||
private static final String XML_ENCODING = "UTF-8";
|
||||
|
||||
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.setXmlFile(buildXmlFile(result));
|
||||
response.getProblems().addAll(result.getProblems());
|
||||
|
||||
if (result.getIndexAnalysis() != null && result.getIndexAnalysis().getCandidates() != null) {
|
||||
@@ -59,4 +67,36 @@ public class IcdToXmlResponseConverter {
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 XML 内容包装为前端展示用的标准文件容器。
|
||||
*/
|
||||
private XmlFileResponse buildXmlFile(IcdToXmlGenerateResult result) {
|
||||
if (result.getXmlContent() == null || result.getXmlContent().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
XmlFileResponse xmlFile = new XmlFileResponse();
|
||||
xmlFile.setFileName(resolveXmlFileName(result));
|
||||
xmlFile.setContentType(XML_CONTENT_TYPE);
|
||||
xmlFile.setEncoding(XML_ENCODING);
|
||||
xmlFile.setContent(result.getXmlContent());
|
||||
return xmlFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* 优先使用 IED 名称构造文件名,缺失时回退默认名。
|
||||
*/
|
||||
private String resolveXmlFileName(IcdToXmlGenerateResult result) {
|
||||
String iedName = result.getIedName();
|
||||
if (iedName == null || iedName.trim().isEmpty()) {
|
||||
return DEFAULT_XML_FILE_NAME;
|
||||
}
|
||||
|
||||
String safeName = iedName.replaceAll("[\\\\/:*?\"<>|]+", "_").trim();
|
||||
if (safeName.isEmpty()) {
|
||||
return DEFAULT_XML_FILE_NAME;
|
||||
}
|
||||
return safeName + ".xml";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,464 @@
|
||||
package com.njcn.gather.icd.mapping.component;
|
||||
|
||||
import com.njcn.gather.icd.mapping.pojo.param.BuildIndexSelectionRequest;
|
||||
import com.njcn.gather.icd.mapping.pojo.param.ConfirmedIndexGroupRequest;
|
||||
import com.njcn.gather.icd.mapping.pojo.param.ConfirmedLabelItemRequest;
|
||||
import com.njcn.gather.icd.mapping.pojo.param.IndexCandidateReportItemRequest;
|
||||
import com.njcn.gather.icd.mapping.pojo.param.IndexCandidateRequest;
|
||||
import com.njcn.gather.icd.mapping.pojo.param.IndexConfirmGroupRequest;
|
||||
import com.njcn.gather.icd.mapping.pojo.param.IndexConfirmLabelItemRequest;
|
||||
import com.njcn.gather.icd.mapping.pojo.param.IndexConfirmTargetRequest;
|
||||
import com.njcn.gather.icd.mapping.pojo.vo.IndexBindingResponse;
|
||||
import com.njcn.gather.icd.mapping.pojo.vo.IndexConfirmGroupResponse;
|
||||
import com.njcn.gather.icd.mapping.pojo.vo.IndexConfirmLabelItemResponse;
|
||||
import com.njcn.gather.icd.mapping.pojo.vo.IndexConfirmTargetResponse;
|
||||
import com.njcn.gather.icd.mapping.pojo.vo.IndexSelectionGroupResponse;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* ICD 结构确认弹窗编排服务。
|
||||
* 第一阶段:把 indexCandidates 整理成前端可确认的 label 级模型。
|
||||
* 第二阶段:根据前端确认结果展开为最终 indexSelection。
|
||||
*/
|
||||
@Service
|
||||
public class IndexSelectionBuildService {
|
||||
|
||||
private static final String GROUP_KEY_STATISTIC = "统计数据__DSSTATISTICDATA";
|
||||
private static final String GROUP_KEY_REALTIME = "实时数据__DSREALTIMEDATA";
|
||||
private static final String DATA_SET_STATISTIC_UNGROUPED = "dsStatisticData";
|
||||
private static final String DATA_SET_STATISTIC_INTER = "dsStIHarm";
|
||||
private static final String DATA_SET_REALTIME_UNGROUPED = "dsRealTimeData";
|
||||
private static final String DATA_SET_REALTIME_INTER = "dsRtIHarm";
|
||||
private static final String LABEL_REALTIME_INTER = "间谐波实时数据";
|
||||
|
||||
private static final Comparator<IndexBindingResponse> INDEX_BINDING_COMPARATOR = (left, right) -> {
|
||||
int result = normalizeSortValue(left == null ? null : left.getReportName())
|
||||
.compareTo(normalizeSortValue(right == null ? null : right.getReportName()));
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
result = normalizeSortValue(left == null ? null : left.getDataSetName())
|
||||
.compareTo(normalizeSortValue(right == null ? null : right.getDataSetName()));
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
return compareLnInstValues(left == null ? null : left.getLnInst(), right == null ? null : right.getLnInst());
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据页面回传的 indexCandidates 生成弹窗确认模型。
|
||||
*/
|
||||
public List<IndexConfirmGroupResponse> buildConfirmData(List<IndexCandidateRequest> indexCandidates) {
|
||||
if (indexCandidates == null || indexCandidates.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<IndexConfirmGroupResponse> result = new ArrayList<IndexConfirmGroupResponse>();
|
||||
for (IndexCandidateRequest candidate : indexCandidates) {
|
||||
if (candidate == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IndexConfirmGroupResponse groupResponse = new IndexConfirmGroupResponse();
|
||||
groupResponse.setGroupKey(candidate.getGroupKey());
|
||||
groupResponse.setGroupDesc(candidate.getGroupDesc());
|
||||
|
||||
if (candidate.getTemplateLabels() != null) {
|
||||
Set<String> uniqueLabels = new LinkedHashSet<String>(candidate.getTemplateLabels());
|
||||
for (String label : uniqueLabels) {
|
||||
if (isBlank(label)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
List<IndexCandidateReportItemRequest> targets = resolveTargets(candidate, label);
|
||||
if (targets.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IndexConfirmLabelItemResponse labelItem = new IndexConfirmLabelItemResponse();
|
||||
labelItem.setLabel(label);
|
||||
labelItem.setRequired(false);
|
||||
labelItem.setConfigurableOnce(true);
|
||||
|
||||
List<List<String>> targetLnInstLists = new ArrayList<List<String>>();
|
||||
for (IndexCandidateReportItemRequest target : targets) {
|
||||
IndexConfirmTargetResponse targetResponse = new IndexConfirmTargetResponse();
|
||||
targetResponse.setReportName(target.getReportName());
|
||||
targetResponse.setDataSetName(target.getDataSetName());
|
||||
targetResponse.setReportDesc(target.getReportDesc());
|
||||
List<String> labelSpecificValues = resolveAvailableLnInstValues(candidate, target, label);
|
||||
targetResponse.getAvailableLnInstValues().addAll(labelSpecificValues);
|
||||
targetLnInstLists.add(labelSpecificValues);
|
||||
labelItem.getTargets().add(targetResponse);
|
||||
}
|
||||
|
||||
List<String> commonLnInstValues = intersectLnInstValues(targetLnInstLists);
|
||||
labelItem.getCommonLnInstValues().addAll(commonLnInstValues);
|
||||
if (commonLnInstValues.size() == 1) {
|
||||
labelItem.setDefaultLnInst(commonLnInstValues.get(0));
|
||||
}
|
||||
if (commonLnInstValues.isEmpty()) {
|
||||
labelItem.setConfigurableOnce(false);
|
||||
}
|
||||
|
||||
groupResponse.getLabelItems().add(labelItem);
|
||||
}
|
||||
}
|
||||
|
||||
result.add(groupResponse);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据确认模型和前端最终确认结果展开生成 indexSelection。
|
||||
*/
|
||||
public List<IndexSelectionGroupResponse> buildIndexSelection(BuildIndexSelectionRequest request) {
|
||||
if (request == null) {
|
||||
throw new IllegalArgumentException("请求体不能为空");
|
||||
}
|
||||
if (request.getConfirmData() == null || request.getConfirmData().isEmpty()) {
|
||||
throw new IllegalArgumentException("confirmData 不能为空");
|
||||
}
|
||||
|
||||
Map<String, IndexConfirmGroupRequest> confirmGroupMap = toConfirmGroupMap(request.getConfirmData());
|
||||
Map<String, ConfirmedIndexGroupRequest> confirmedGroupMap = toConfirmedGroupMap(request.getConfirmedData());
|
||||
validateConfirmedGroups(confirmGroupMap, confirmedGroupMap);
|
||||
|
||||
List<IndexSelectionGroupResponse> result = new ArrayList<IndexSelectionGroupResponse>();
|
||||
for (IndexConfirmGroupRequest confirmGroup : request.getConfirmData()) {
|
||||
if (confirmGroup == null || isBlank(confirmGroup.getGroupKey())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ConfirmedIndexGroupRequest confirmedGroup = confirmedGroupMap.get(confirmGroup.getGroupKey());
|
||||
if (confirmedGroup == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map<String, ConfirmedLabelItemRequest> confirmedLabelMap = toConfirmedLabelMap(confirmedGroup.getLabelItems());
|
||||
validateConfirmedLabels(confirmGroup, confirmedLabelMap);
|
||||
IndexSelectionGroupResponse selectionGroup = new IndexSelectionGroupResponse();
|
||||
selectionGroup.setGroupKey(confirmGroup.getGroupKey());
|
||||
selectionGroup.setGroupDesc(confirmGroup.getGroupDesc());
|
||||
|
||||
if (confirmGroup.getLabelItems() != null) {
|
||||
for (IndexConfirmLabelItemRequest confirmLabel : confirmGroup.getLabelItems()) {
|
||||
if (confirmLabel == null || isBlank(confirmLabel.getLabel())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ConfirmedLabelItemRequest confirmedLabel = confirmedLabelMap.get(confirmLabel.getLabel());
|
||||
if (confirmedLabel == null || !confirmedLabel.isEnabled()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
validateConfirmedLabel(confirmGroupMap, confirmGroup, confirmLabel, confirmedLabel);
|
||||
expandBindings(selectionGroup, confirmLabel, confirmedLabel.getLnInst());
|
||||
}
|
||||
}
|
||||
|
||||
if (!selectionGroup.getBindings().isEmpty()) {
|
||||
// 返回前统一排序,避免前端展示顺序受展开过程影响。
|
||||
selectionGroup.getBindings().sort(INDEX_BINDING_COMPARATOR);
|
||||
result.add(selectionGroup);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void validateConfirmedGroups(Map<String, IndexConfirmGroupRequest> confirmGroupMap,
|
||||
Map<String, ConfirmedIndexGroupRequest> confirmedGroupMap) {
|
||||
for (String groupKey : confirmedGroupMap.keySet()) {
|
||||
if (!confirmGroupMap.containsKey(groupKey)) {
|
||||
throw new IllegalArgumentException("confirmedData 中存在未知分组:" + groupKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateConfirmedLabels(IndexConfirmGroupRequest confirmGroup,
|
||||
Map<String, ConfirmedLabelItemRequest> confirmedLabelMap) {
|
||||
if (confirmedLabelMap.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Set<String> allowedLabels = new LinkedHashSet<String>();
|
||||
if (confirmGroup.getLabelItems() != null) {
|
||||
for (IndexConfirmLabelItemRequest labelItem : confirmGroup.getLabelItems()) {
|
||||
if (labelItem != null && !isBlank(labelItem.getLabel())) {
|
||||
allowedLabels.add(labelItem.getLabel());
|
||||
}
|
||||
}
|
||||
}
|
||||
for (String label : confirmedLabelMap.keySet()) {
|
||||
if (!allowedLabels.contains(label)) {
|
||||
throw new IllegalArgumentException("分组【" + confirmGroup.getGroupDesc() + "】中存在未知标签:" + label);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, IndexConfirmGroupRequest> toConfirmGroupMap(List<IndexConfirmGroupRequest> confirmData) {
|
||||
Map<String, IndexConfirmGroupRequest> result = new LinkedHashMap<String, IndexConfirmGroupRequest>();
|
||||
if (confirmData == null) {
|
||||
return result;
|
||||
}
|
||||
for (IndexConfirmGroupRequest group : confirmData) {
|
||||
if (group != null && !isBlank(group.getGroupKey())) {
|
||||
result.put(group.getGroupKey(), group);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Map<String, ConfirmedIndexGroupRequest> toConfirmedGroupMap(List<ConfirmedIndexGroupRequest> confirmedData) {
|
||||
Map<String, ConfirmedIndexGroupRequest> result = new LinkedHashMap<String, ConfirmedIndexGroupRequest>();
|
||||
if (confirmedData == null) {
|
||||
return result;
|
||||
}
|
||||
for (ConfirmedIndexGroupRequest group : confirmedData) {
|
||||
if (group != null && !isBlank(group.getGroupKey())) {
|
||||
result.put(group.getGroupKey(), group);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Map<String, ConfirmedLabelItemRequest> toConfirmedLabelMap(List<ConfirmedLabelItemRequest> labelItems) {
|
||||
Map<String, ConfirmedLabelItemRequest> result = new LinkedHashMap<String, ConfirmedLabelItemRequest>();
|
||||
if (labelItems == null) {
|
||||
return result;
|
||||
}
|
||||
for (ConfirmedLabelItemRequest item : labelItems) {
|
||||
if (item != null && !isBlank(item.getLabel())) {
|
||||
result.put(item.getLabel(), item);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计数据、实时数据存在“同一 label 只配一次”的特殊归并规则,
|
||||
* 其他分组默认把同名 label 展开到当前分组下全部报告。
|
||||
*/
|
||||
private List<IndexCandidateReportItemRequest> resolveTargets(IndexCandidateRequest candidate, String label) {
|
||||
List<IndexCandidateReportItemRequest> reports = candidate.getReports();
|
||||
if (reports == null || reports.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
boolean hasRealtimeInterReport = hasDataSet(reports, DATA_SET_REALTIME_INTER);
|
||||
List<IndexCandidateReportItemRequest> result = new ArrayList<IndexCandidateReportItemRequest>();
|
||||
for (IndexCandidateReportItemRequest report : reports) {
|
||||
if (report == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (GROUP_KEY_STATISTIC.equals(candidate.getGroupKey())) {
|
||||
if (isInterHarmonicLabel(label)) {
|
||||
if (DATA_SET_STATISTIC_INTER.equals(report.getDataSetName()) || reports.size() == 1) {
|
||||
result.add(report);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!DATA_SET_STATISTIC_INTER.equals(report.getDataSetName())) {
|
||||
result.add(report);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (GROUP_KEY_REALTIME.equals(candidate.getGroupKey())) {
|
||||
if (LABEL_REALTIME_INTER.equals(label)) {
|
||||
if (DATA_SET_REALTIME_INTER.equals(report.getDataSetName())) {
|
||||
result.add(report);
|
||||
} else if (!hasRealtimeInterReport && DATA_SET_REALTIME_UNGROUPED.equals(report.getDataSetName())) {
|
||||
result.add(report);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!DATA_SET_REALTIME_INTER.equals(report.getDataSetName())) {
|
||||
result.add(report);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
result.add(report);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean hasDataSet(List<IndexCandidateReportItemRequest> reports, String dataSetName) {
|
||||
if (reports == null || reports.isEmpty() || isBlank(dataSetName)) {
|
||||
return false;
|
||||
}
|
||||
for (IndexCandidateReportItemRequest report : reports) {
|
||||
if (report != null && dataSetName.equals(report.getDataSetName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算多个目标报告可共同接受的 lnInst 候选,保持首个目标报告的顺序。
|
||||
*/
|
||||
private List<String> intersectLnInstValues(List<List<String>> targetLnInstLists) {
|
||||
if (targetLnInstLists == null || targetLnInstLists.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<String> firstValues = targetLnInstLists.get(0);
|
||||
if (firstValues == null || firstValues.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<String> result = new ArrayList<String>();
|
||||
for (String value : firstValues) {
|
||||
if (isBlank(value)) {
|
||||
continue;
|
||||
}
|
||||
boolean existsInAllTargets = true;
|
||||
for (int i = 1; i < targetLnInstLists.size(); i++) {
|
||||
List<String> currentValues = targetLnInstLists.get(i);
|
||||
if (currentValues == null || !currentValues.contains(value)) {
|
||||
existsInAllTargets = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (existsInAllTargets) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 某些未分组报告会把多种 label 的候选值拼在同一个 availableLnInstValues 里,
|
||||
* 这里按当前业务规则先拆开后再返回给前端。
|
||||
*/
|
||||
private List<String> resolveAvailableLnInstValues(IndexCandidateRequest candidate,
|
||||
IndexCandidateReportItemRequest target,
|
||||
String label) {
|
||||
if (target == null || target.getAvailableLnInstValues() == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<String> values = target.getAvailableLnInstValues();
|
||||
if (GROUP_KEY_STATISTIC.equals(candidate.getGroupKey())
|
||||
&& DATA_SET_STATISTIC_UNGROUPED.equals(target.getDataSetName())
|
||||
&& values.size() > 1) {
|
||||
int splitIndex = values.size() / 2;
|
||||
return isInterHarmonicLabel(label)
|
||||
? new ArrayList<String>(values.subList(splitIndex, values.size()))
|
||||
: new ArrayList<String>(values.subList(0, splitIndex));
|
||||
}
|
||||
|
||||
if (GROUP_KEY_REALTIME.equals(candidate.getGroupKey())
|
||||
&& DATA_SET_REALTIME_UNGROUPED.equals(target.getDataSetName())
|
||||
&& values.size() > 1) {
|
||||
return LABEL_REALTIME_INTER.equals(label)
|
||||
? new ArrayList<String>(values.subList(1, values.size()))
|
||||
: new ArrayList<String>(values.subList(0, 1));
|
||||
}
|
||||
|
||||
return new ArrayList<String>(values);
|
||||
}
|
||||
|
||||
private void validateConfirmedLabel(Map<String, IndexConfirmGroupRequest> confirmGroupMap,
|
||||
IndexConfirmGroupRequest confirmGroup,
|
||||
IndexConfirmLabelItemRequest confirmLabel,
|
||||
ConfirmedLabelItemRequest confirmedLabel) {
|
||||
if (!confirmGroupMap.containsKey(confirmGroup.getGroupKey())) {
|
||||
throw new IllegalArgumentException("未找到确认分组:" + confirmGroup.getGroupKey());
|
||||
}
|
||||
if (isBlank(confirmedLabel.getLnInst())) {
|
||||
throw new IllegalArgumentException("分组【" + confirmGroup.getGroupDesc() + "】的标签【"
|
||||
+ confirmLabel.getLabel() + "】未选择 lnInst");
|
||||
}
|
||||
if (confirmLabel.getCommonLnInstValues() == null || !confirmLabel.getCommonLnInstValues().contains(confirmedLabel.getLnInst())) {
|
||||
throw new IllegalArgumentException(
|
||||
"分组【" + confirmGroup.getGroupDesc() + "】的标签【" + confirmLabel.getLabel()
|
||||
+ "】选择的 lnInst【" + confirmedLabel.getLnInst() + "】不在共同候选范围内:"
|
||||
+ confirmLabel.getCommonLnInstValues()
|
||||
);
|
||||
}
|
||||
if (confirmLabel.getTargets() != null) {
|
||||
for (IndexConfirmTargetRequest target : confirmLabel.getTargets()) {
|
||||
if (target == null || target.getAvailableLnInstValues() == null) {
|
||||
continue;
|
||||
}
|
||||
if (!target.getAvailableLnInstValues().contains(confirmedLabel.getLnInst())) {
|
||||
throw new IllegalArgumentException(
|
||||
"标签【" + confirmLabel.getLabel() + "】在目标报告【" + target.getReportName()
|
||||
+ "】下不支持 lnInst【" + confirmedLabel.getLnInst() + "】"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void expandBindings(IndexSelectionGroupResponse selectionGroup,
|
||||
IndexConfirmLabelItemRequest confirmLabel,
|
||||
String lnInst) {
|
||||
if (confirmLabel.getTargets() == null) {
|
||||
return;
|
||||
}
|
||||
for (IndexConfirmTargetRequest target : confirmLabel.getTargets()) {
|
||||
if (target == null) {
|
||||
continue;
|
||||
}
|
||||
IndexBindingResponse binding = new IndexBindingResponse();
|
||||
binding.setReportName(target.getReportName());
|
||||
binding.setDataSetName(target.getDataSetName());
|
||||
binding.setLabel(confirmLabel.getLabel());
|
||||
binding.setLnInst(lnInst);
|
||||
selectionGroup.getBindings().add(binding);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInterHarmonicLabel(String label) {
|
||||
return label != null && label.startsWith("间谐波");
|
||||
}
|
||||
|
||||
private static String normalizeSortValue(String value) {
|
||||
return value == null ? "" : value;
|
||||
}
|
||||
|
||||
private static int compareLnInstValues(String left, String right) {
|
||||
Long leftNumeric = parseNumericLnInst(left);
|
||||
Long rightNumeric = parseNumericLnInst(right);
|
||||
if (leftNumeric != null && rightNumeric != null) {
|
||||
int result = leftNumeric.compareTo(rightNumeric);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return normalizeSortValue(left).compareTo(normalizeSortValue(right));
|
||||
}
|
||||
|
||||
private static Long parseNumericLnInst(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String trimmedValue = value.trim();
|
||||
if (trimmedValue.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return Long.valueOf(trimmedValue);
|
||||
} catch (NumberFormatException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBlank(String value) {
|
||||
return value == null || value.trim().isEmpty();
|
||||
}
|
||||
}
|
||||
@@ -54,14 +54,7 @@ public class JsonToXmlConversionService {
|
||||
InputStream templateStream,
|
||||
List<InputStream> 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);
|
||||
String xmlContent = buildXmlContentFromJson(mappingJson, templateStream, ruleStreams, indexMapping);
|
||||
|
||||
// 3. 保存为临时文件
|
||||
Path tempPath = Files.createTempFile("converted_", ".xml");
|
||||
@@ -69,6 +62,33 @@ public class JsonToXmlConversionService {
|
||||
|
||||
return tempPath.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 JSON 字符串转换为 XML 内容,供前端直接展示。
|
||||
*
|
||||
* @param mappingJson JSON 格式的映射文档
|
||||
* @param templateStream XML 模板流
|
||||
* @param ruleStreams 规则文件流列表
|
||||
* @param indexMapping 索引映射配置
|
||||
* @return 生成后的 XML 内容
|
||||
* @throws Exception 转换异常
|
||||
*/
|
||||
public String buildXmlContentFromJson(String mappingJson,
|
||||
InputStream templateStream,
|
||||
List<InputStream> ruleStreams,
|
||||
IcdToXmlMappingService.IndexMappingConfig indexMapping) throws Exception {
|
||||
return buildXmlContentFromJson(mappingJson, templateStream, ruleStreams, indexMapping, null);
|
||||
}
|
||||
|
||||
public String buildXmlContentFromJson(String mappingJson,
|
||||
InputStream templateStream,
|
||||
List<InputStream> ruleStreams,
|
||||
IcdToXmlMappingService.IndexMappingConfig indexMapping,
|
||||
List<String> methodDescribeList) throws Exception {
|
||||
// 反序列化 JSON 后复用现有规则引擎生成 XML,避免文件输出链路重复实现。
|
||||
MappingDocument mappingDocument = objectMapper.readValue(mappingJson, MappingDocument.class);
|
||||
return buildXmlFromMapping(mappingDocument, templateStream, ruleStreams, indexMapping, methodDescribeList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从MappingDocument构建XML内容
|
||||
@@ -76,7 +96,8 @@ public class JsonToXmlConversionService {
|
||||
private String buildXmlFromMapping(MappingDocument mappingDocument,
|
||||
InputStream templateStream,
|
||||
List<InputStream> ruleStreams,
|
||||
IcdToXmlMappingService.IndexMappingConfig indexMapping) throws Exception {
|
||||
IcdToXmlMappingService.IndexMappingConfig indexMapping,
|
||||
List<String> methodDescribeList) throws Exception {
|
||||
|
||||
String templateContent = readInputStreamToString(templateStream);
|
||||
|
||||
@@ -84,7 +105,7 @@ public class JsonToXmlConversionService {
|
||||
|
||||
xmlContent = fillReportControlsFromMapping(xmlContent, mappingDocument);
|
||||
|
||||
xmlContent = applyRulesFromMapping(xmlContent, mappingDocument, ruleStreams, indexMapping);
|
||||
xmlContent = applyRulesFromMapping(xmlContent, mappingDocument, ruleStreams, indexMapping, methodDescribeList);
|
||||
|
||||
return xmlContent;
|
||||
}
|
||||
@@ -217,21 +238,22 @@ public class JsonToXmlConversionService {
|
||||
private String applyRulesFromMapping(String xmlContent,
|
||||
MappingDocument mappingDocument,
|
||||
List<InputStream> ruleStreams,
|
||||
IcdToXmlMappingService.IndexMappingConfig indexMapping) throws Exception {
|
||||
IcdToXmlMappingService.IndexMappingConfig indexMapping,
|
||||
List<String> methodDescribeList) 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());
|
||||
addMethodDescribe(methodDescribeList, "========== 开始从JSON匹配规则 ==========");
|
||||
addMethodDescribe(methodDescribeList, "规则总数: " + mergedRules.size());
|
||||
addMethodDescribe(methodDescribeList, "JSON中指标总数: " + mappingMetrics.size());
|
||||
|
||||
var applicableRules = findApplicableRulesDesc(mergedRules, mappingMetrics);
|
||||
var applicableRules = findApplicableRulesDesc(mergedRules, mappingMetrics, methodDescribeList);
|
||||
|
||||
System.out.println("匹配成功: " + applicableRules.size() + " 条规则");
|
||||
System.out.println("匹配失败: " + (mergedRules.size() - applicableRules.size()) + " 条规则");
|
||||
System.out.println("========== JSON规则匹配结束 ==========\n");
|
||||
addMethodDescribe(methodDescribeList, "匹配成功: " + applicableRules.size() + " 条规则");
|
||||
addMethodDescribe(methodDescribeList, "匹配失败: " + (mergedRules.size() - applicableRules.size()) + " 条规则");
|
||||
addMethodDescribe(methodDescribeList, "========== JSON规则匹配结束 ==========");
|
||||
|
||||
return applyRulesToXml(xmlContent, applicableRules);
|
||||
}
|
||||
@@ -731,7 +753,8 @@ public class JsonToXmlConversionService {
|
||||
*/
|
||||
private java.util.Map<String, RuleBasedXmlMappingService.ValueRule> findApplicableRulesDesc(
|
||||
java.util.Map<String, List<RuleBasedXmlMappingService.ValueRule>> allRules,
|
||||
java.util.Map<String, MetricInfo> mappingMetrics) {
|
||||
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<>();
|
||||
@@ -753,7 +776,7 @@ public class JsonToXmlConversionService {
|
||||
rule.setDaPath(metric.getDaPath());
|
||||
applicable.put(ruleKey, rule);
|
||||
matched = true;
|
||||
System.out.println("✓ 规则匹配成功: " + ruleKey + " -> DO=" + rule.getDoPath() + ", DA=" + rule.getDaPath());
|
||||
addMethodDescribe(methodDescribeList, "✓ 规则匹配成功: " + ruleKey + " -> DO=" + rule.getDoPath() + ", DA=" + rule.getDaPath());
|
||||
|
||||
}
|
||||
|
||||
@@ -765,22 +788,22 @@ public class JsonToXmlConversionService {
|
||||
|
||||
if (!matched) {
|
||||
failedRules.add(ruleKey);
|
||||
System.out.println("✗ 规则匹配失败: " + ruleKey + " (共" + ruleVariants.size() + "个候选)");
|
||||
addMethodDescribe(methodDescribeList, "✗ 规则匹配失败: " + ruleKey + " (共" + ruleVariants.size() + "个候选)");
|
||||
for (RuleBasedXmlMappingService.ValueRule rule : ruleVariants) {
|
||||
System.out.println(" 候选指标名: " + rule.getName());
|
||||
addMethodDescribe(methodDescribeList, " 候选指标名: " + rule.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("\n========== 详细匹配结果 ==========");
|
||||
System.out.println("成功匹配的规则 (" + applicable.size() + " 条):");
|
||||
addMethodDescribe(methodDescribeList, "========== 详细匹配结果 ==========");
|
||||
addMethodDescribe(methodDescribeList, "成功匹配的规则 (" + applicable.size() + " 条):");
|
||||
for (String key : applicable.keySet()) {
|
||||
System.out.println(" - " + key);
|
||||
addMethodDescribe(methodDescribeList, " - " + key);
|
||||
}
|
||||
|
||||
System.out.println("\n失败匹配的规则 (" + failedRules.size() + " 条):");
|
||||
addMethodDescribe(methodDescribeList, "失败匹配的规则 (" + failedRules.size() + " 条):");
|
||||
for (String key : failedRules) {
|
||||
System.out.println(" - " + key);
|
||||
addMethodDescribe(methodDescribeList, " - " + key);
|
||||
}
|
||||
|
||||
return applicable;
|
||||
@@ -818,7 +841,7 @@ public class JsonToXmlConversionService {
|
||||
if (matchesPattern(ruleDo, icdDo) && matchesPattern(ruleDa, icdDa)) {
|
||||
applicable.put(ruleKey, rule);
|
||||
matched = true;
|
||||
System.out.println("✓ 规则匹配成功: " + ruleKey + " -> DO=" + rule.getDoPath() + ", DA=" + rule.getDaPath());
|
||||
addMethodDescribe(null, "✓ 规则匹配成功: " + ruleKey + " -> DO=" + rule.getDoPath() + ", DA=" + rule.getDaPath());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -830,22 +853,22 @@ public class JsonToXmlConversionService {
|
||||
|
||||
if (!matched) {
|
||||
failedRules.add(ruleKey);
|
||||
System.out.println("✗ 规则匹配失败: " + ruleKey + " (共" + ruleVariants.size() + "个候选)");
|
||||
addMethodDescribe(null, "✗ 规则匹配失败: " + ruleKey + " (共" + ruleVariants.size() + "个候选)");
|
||||
for (RuleBasedXmlMappingService.ValueRule rule : ruleVariants) {
|
||||
System.out.println(" 候选: DO=" + rule.getDoPath() + ", DA=" + rule.getDaPath());
|
||||
addMethodDescribe(null, " 候选: DO=" + rule.getDoPath() + ", DA=" + rule.getDaPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("\n========== 详细匹配结果 ==========");
|
||||
System.out.println("成功匹配的规则 (" + applicable.size() + " 条):");
|
||||
addMethodDescribe(null, "========== 详细匹配结果 ==========");
|
||||
addMethodDescribe(null, "成功匹配的规则 (" + applicable.size() + " 条):");
|
||||
for (String key : applicable.keySet()) {
|
||||
System.out.println(" - " + key);
|
||||
addMethodDescribe(null, " - " + key);
|
||||
}
|
||||
|
||||
System.out.println("\n失败匹配的规则 (" + failedRules.size() + " 条):");
|
||||
addMethodDescribe(null, "失败匹配的规则 (" + failedRules.size() + " 条):");
|
||||
for (String key : failedRules) {
|
||||
System.out.println(" - " + key);
|
||||
addMethodDescribe(null, " - " + key);
|
||||
}
|
||||
|
||||
return applicable;
|
||||
@@ -952,6 +975,13 @@ public class JsonToXmlConversionService {
|
||||
.replace("\"", """)
|
||||
.replace("'", "'");
|
||||
}
|
||||
|
||||
private void addMethodDescribe(List<String> methodDescribeList, String message) {
|
||||
if (methodDescribeList == null || message == null || message.trim().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
methodDescribeList.add(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 指标信息内部类
|
||||
|
||||
@@ -38,6 +38,7 @@ public class MappingResponseConverter {
|
||||
MappingTaskResponse response = initBaseResponse(result);
|
||||
if (result.getStatus() == GenerateStatus.SUCCESS) {
|
||||
response.setMappingJson(result.getMappingJson());
|
||||
response.setMappingDocument(result.getMappingDocument());
|
||||
response.setSavedPath(result.getSavedPath());
|
||||
return response;
|
||||
}
|
||||
@@ -82,4 +83,4 @@ public class MappingResponseConverter {
|
||||
response.getIndexCandidates().add(candidateResponse);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,26 +2,33 @@ package com.njcn.gather.icd.mapping.controller;
|
||||
|
||||
import com.njcn.common.pojo.annotation.OperateInfo;
|
||||
import com.njcn.common.pojo.enums.common.LogEnum;
|
||||
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
|
||||
import com.njcn.common.pojo.response.HttpResult;
|
||||
import com.njcn.common.utils.LogUtil;
|
||||
import com.njcn.gather.icd.mapping.component.IcdToXmlRequestConverter;
|
||||
import com.njcn.gather.icd.mapping.component.IcdToXmlResponseConverter;
|
||||
import com.njcn.gather.icd.mapping.component.IndexSelectionBuildService;
|
||||
import com.njcn.gather.icd.mapping.component.MappingRequestConverter;
|
||||
import com.njcn.gather.icd.mapping.component.MappingResponseConverter;
|
||||
import com.njcn.gather.icd.mapping.pojo.bo.GenerateMappingResult;
|
||||
import com.njcn.gather.icd.mapping.pojo.bo.IcdToXmlGenerateResult;
|
||||
import com.njcn.gather.icd.mapping.pojo.dto.GenerateFromIcdCommand;
|
||||
import com.njcn.gather.icd.mapping.pojo.dto.IcdToXmlGenerateCommand;
|
||||
import com.njcn.gather.icd.mapping.pojo.param.BuildIndexSelectionRequest;
|
||||
import com.njcn.gather.icd.mapping.pojo.param.GenerateMappingFromIcdRequest;
|
||||
import com.njcn.gather.icd.mapping.pojo.param.IcdToXmlGenerateRequest;
|
||||
import com.njcn.gather.icd.mapping.pojo.param.IndexCandidateRequest;
|
||||
import com.njcn.gather.icd.mapping.pojo.param.JsonToXmlRequest;
|
||||
import com.njcn.gather.icd.mapping.pojo.param.SubmitIndexSelectionRequest;
|
||||
import com.njcn.gather.icd.mapping.pojo.vo.IcdToXmlResponse;
|
||||
import com.njcn.gather.icd.mapping.pojo.vo.IndexConfirmGroupResponse;
|
||||
import com.njcn.gather.icd.mapping.pojo.vo.IndexSelectionGroupResponse;
|
||||
import com.njcn.gather.icd.mapping.pojo.vo.MappingTaskResponse;
|
||||
import com.njcn.gather.icd.mapping.service.MappingTaskService;
|
||||
import com.njcn.gather.icd.mapping.service.impl.IcdToXmlTaskAppService;
|
||||
import com.njcn.gather.icd.mapping.utils.DateUtils;
|
||||
import com.njcn.web.controller.BaseController;
|
||||
import com.njcn.web.utils.HttpResultUtil;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -33,6 +40,8 @@ import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* ICD 映射接口入口。
|
||||
*/
|
||||
@@ -55,17 +64,18 @@ public class MappingController extends BaseController {
|
||||
/** 请求参数转换器,将接口入参转换为应用层命令。 */
|
||||
private final IcdToXmlResponseConverter icdResponseConverter;
|
||||
|
||||
/** 响应转换器,按接口阶段裁剪最小返回字段。 */
|
||||
private final IcdToXmlRequestConverter icdRequestConverter;
|
||||
|
||||
/** 响应转换器,按接口阶段裁剪最小返回字段。 */
|
||||
private final IcdToXmlTaskAppService icdToXmlTaskAppService;
|
||||
|
||||
/** ICD 结构确认弹窗结果组装服务。 */
|
||||
private final IndexSelectionBuildService indexSelectionBuildService;
|
||||
|
||||
/**
|
||||
* 上传 ICD 文件,返回候选结果和可编辑的 ICD 解析结果。
|
||||
*/
|
||||
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
|
||||
@ApiOperation("上传 ICD 文件并生成索引候选")
|
||||
@ApiImplicitParam(name = "icdFile", value = "ICD 文件", required = true, dataType = "__file", paramType = "form")
|
||||
@PostMapping(value = "/get-icd", consumes = {"multipart/form-data"})
|
||||
public MappingTaskResponse getICD(@RequestPart("icdFile") MultipartFile icdFile) {
|
||||
String methodDescribe = getMethodDescribe("getICD");
|
||||
@@ -80,6 +90,7 @@ public class MappingController extends BaseController {
|
||||
*/
|
||||
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
|
||||
@ApiOperation("获取 MMS JSON")
|
||||
@ApiImplicitParam(name = "request", value = "索引确认后生成 MMS JSON 参数", required = true, dataType = "SubmitIndexSelectionRequest")
|
||||
@PostMapping("/get-mms-json")
|
||||
public MappingTaskResponse getMmsJson(@Validated @RequestBody SubmitIndexSelectionRequest request) {
|
||||
String methodDescribe = getMethodDescribe("getMmsJson");
|
||||
@@ -95,6 +106,10 @@ public class MappingController extends BaseController {
|
||||
*/
|
||||
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
|
||||
@ApiOperation("上传 ICD 后直接获取 MMS JSON")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "icdFile", value = "ICD 文件", required = true, dataType = "__file", paramType = "form"),
|
||||
@ApiImplicitParam(name = "request", value = "上传 ICD 后直接生成映射参数", required = true, dataType = "GenerateMappingFromIcdRequest", paramType = "form")
|
||||
})
|
||||
@PostMapping(value = "/get-icd-mms-json", consumes = {"multipart/form-data"})
|
||||
public MappingTaskResponse getIcdMmsJson(@RequestPart("icdFile") MultipartFile icdFile,
|
||||
@Validated @RequestPart("request") GenerateMappingFromIcdRequest request) {
|
||||
@@ -108,25 +123,58 @@ public class MappingController extends BaseController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接将 MMS JSON 转换为 XML 文件。
|
||||
* 根据页面回传的 indexCandidates 生成弹窗确认模型。
|
||||
*/
|
||||
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
|
||||
@ApiOperation("根据 indexCandidates 生成确认数据")
|
||||
@ApiImplicitParam(name = "indexCandidates", value = "索引候选分组列表", required = true, dataType = "List")
|
||||
@PostMapping("/build-index-confirm-data")
|
||||
public HttpResult<List<IndexConfirmGroupResponse>> buildIndexConfirmData(@RequestBody List<IndexCandidateRequest> indexCandidates) {
|
||||
String methodDescribe = getMethodDescribe("buildIndexConfirmData");
|
||||
LogUtil.njcnDebug(log, "{},开始根据 indexCandidates 生成确认数据,candidateCount={}",
|
||||
methodDescribe, indexCandidates == null ? 0 : indexCandidates.size());
|
||||
List<IndexConfirmGroupResponse> result = indexSelectionBuildService.buildConfirmData(indexCandidates);
|
||||
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据前端确认后的结果生成最终 indexSelection。
|
||||
*/
|
||||
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
|
||||
@ApiOperation("根据确认结果生成 indexSelection")
|
||||
@ApiImplicitParam(name = "request", value = "根据确认结果生成 indexSelection 参数", required = true, dataType = "BuildIndexSelectionRequest")
|
||||
@PostMapping("/build-index-selection")
|
||||
public HttpResult<List<IndexSelectionGroupResponse>> buildIndexSelection(@RequestBody BuildIndexSelectionRequest request) {
|
||||
String methodDescribe = getMethodDescribe("buildIndexSelection");
|
||||
LogUtil.njcnDebug(log, "{},开始根据确认结果生成 indexSelection,confirmGroupCount={}, confirmedGroupCount={}",
|
||||
methodDescribe,
|
||||
request == null || request.getConfirmData() == null ? 0 : request.getConfirmData().size(),
|
||||
request == null || request.getConfirmedData() == null ? 0 : request.getConfirmedData().size());
|
||||
List<IndexSelectionGroupResponse> result = indexSelectionBuildService.buildIndexSelection(request);
|
||||
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接将 MMS JSON 转换为 XML 内容。
|
||||
* 适用于已经通过 getIcdMmsJson 获得 JSON 后,单独进行 XML 转换的场景。
|
||||
*/
|
||||
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
|
||||
@ApiOperation("MMS JSON 转 XML")
|
||||
@ApiImplicitParam(name = "request", value = "MMS JSON 转 XML 参数", required = true, dataType = "JsonToXmlRequest")
|
||||
@PostMapping("/get-xml-from-json")
|
||||
public IcdToXmlResponse getXmlFromJson(@Validated @RequestPart("request") JsonToXmlRequest request) {
|
||||
String methodDescribe = getMethodDescribe("getXmlFromJson");
|
||||
LogUtil.njcnDebug(log, "{},开始将 MMS JSON 转换为 XML", methodDescribe);
|
||||
String methodDescribe = getMethodDescribe("getXmlFromJson") + ",开始将 MMS JSON 转换为 XML";
|
||||
|
||||
// // 将请求参数转换为 Command
|
||||
// IcdToXmlGenerateCommand command =
|
||||
// icdRequestConverter.toCommand(request);
|
||||
//
|
||||
// 调用服务生成 XML
|
||||
// 直接返回 XML 内容给前端展示,不再输出临时文件。
|
||||
IcdToXmlGenerateResult result =
|
||||
icdToXmlTaskAppService.generateXmlFromJson(request.getMappingJson());
|
||||
icdToXmlTaskAppService.generateXmlFromJson(request == null ? null : request.getMappingJson());
|
||||
if (result.getMethodDescribe() != null && !result.getMethodDescribe().trim().isEmpty()) {
|
||||
methodDescribe = methodDescribe + "\n" + result.getMethodDescribe();
|
||||
}
|
||||
|
||||
return icdResponseConverter.fromResult(result);
|
||||
IcdToXmlResponse response = icdResponseConverter.fromResult(result);
|
||||
response.setMethodDescribe(methodDescribe);
|
||||
return response;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ public class SclGeneratedModelReader {
|
||||
* 从 LN0 或 LN 中读取 DataSet 与 ReportControl 信息。
|
||||
*/
|
||||
private void readReportAndDataSetFromAnyLn(TAnyLN anyLn, IcdDocument document) {
|
||||
List<FcdaNode> allFcdas = new ArrayList<FcdaNode>();
|
||||
//List<FcdaNode> allFcdas = new ArrayList<FcdaNode>();
|
||||
if (anyLn.getDataSet() != null) {
|
||||
for (TDataSet dataSet : anyLn.getDataSet()) {
|
||||
DataSetNode dataSetNode = new DataSetNode();
|
||||
@@ -105,7 +105,7 @@ public class SclGeneratedModelReader {
|
||||
for (TFCDA fcda : dataSet.getFCDA()) {
|
||||
FcdaNode node = toFcdaNode(fcda);
|
||||
dataSetNode.getFcdas().add(node);
|
||||
allFcdas.add(node);
|
||||
//allFcdas.add(node);
|
||||
}
|
||||
}
|
||||
document.getDataSets().put(dataSetNode.getName(), dataSetNode);
|
||||
@@ -113,7 +113,7 @@ public class SclGeneratedModelReader {
|
||||
}
|
||||
for (DataSetNode dataSet : document.getDataSets().values()) {
|
||||
for (FcdaNode fcda : dataSet.getFcdas()) {
|
||||
fcda.setSequenceCount(SclTraversalSupport.calculateSequenceCount(allFcdas, fcda));
|
||||
fcda.setSequenceCount(SclTraversalSupport.calculateSequenceCount(dataSet.getFcdas(), fcda));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,36 +3,42 @@ package com.njcn.gather.icd.mapping.pojo.bo;
|
||||
import com.njcn.gather.icd.mapping.pojo.bo.analysis.IndexAnalysis;
|
||||
import com.njcn.gather.icd.mapping.pojo.bo.mapping.MappingDocument;
|
||||
import com.njcn.gather.icd.mapping.pojo.enums.GenerateStatus;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* XML 生成应用层返回对象。
|
||||
*
|
||||
* 统一封装成功、需选择索引、失败三类结果。
|
||||
*/
|
||||
@Data
|
||||
public class IcdToXmlGenerateResult {
|
||||
/** 本次生成流程状态。 */
|
||||
private GenerateStatus status;
|
||||
private String message;
|
||||
private String iedName;
|
||||
private String ldInst;
|
||||
private IndexAnalysis indexAnalysis;
|
||||
private MappingDocument mappingDocument;
|
||||
private String savedPath;
|
||||
private List<String> problems = new ArrayList<String>();
|
||||
|
||||
public GenerateStatus getStatus() { return status; }
|
||||
public void setStatus(GenerateStatus status) { this.status = status; }
|
||||
public String getMessage() { return message; }
|
||||
public void setMessage(String message) { this.message = message; }
|
||||
public String getIedName() { return iedName; }
|
||||
public void setIedName(String iedName) { this.iedName = iedName; }
|
||||
public String getLdInst() { return ldInst; }
|
||||
public void setLdInst(String ldInst) { this.ldInst = ldInst; }
|
||||
public IndexAnalysis getIndexAnalysis() { return indexAnalysis; }
|
||||
public void setIndexAnalysis(IndexAnalysis indexAnalysis) { this.indexAnalysis = indexAnalysis; }
|
||||
public MappingDocument getMappingDocument() { return mappingDocument; }
|
||||
public void setMappingDocument(MappingDocument mappingDocument) { this.mappingDocument = mappingDocument; }
|
||||
public String getSavedPath() { return savedPath; }
|
||||
public void setSavedPath(String savedPath) { this.savedPath = savedPath; }
|
||||
public List<String> getProblems() { return problems; }
|
||||
public void setProblems(List<String> problems) { this.problems = problems; }
|
||||
}
|
||||
/** 给前端或调用方展示的处理结果说明。 */
|
||||
private String message;
|
||||
|
||||
/** 生成过程中需要返回的方法描述信息。 */
|
||||
private String methodDescribe;
|
||||
|
||||
/** ICD 中解析到的 IED 名称。 */
|
||||
private String iedName;
|
||||
|
||||
/** ICD 中解析到的 LD 实例名。 */
|
||||
private String ldInst;
|
||||
|
||||
/** 需要人工绑定索引时返回的候选分析结果。 */
|
||||
private IndexAnalysis indexAnalysis;
|
||||
|
||||
/** 生成成功后的结构化映射文档。 */
|
||||
private MappingDocument mappingDocument;
|
||||
|
||||
/** 生成成功后的 XML 内容,用于前端直接展示。 */
|
||||
private String xmlContent;
|
||||
|
||||
/** 解析、校验或生成过程中收集到的问题。 */
|
||||
private List<String> problems = new ArrayList<String>();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.param;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 根据确认结果生成 indexSelection 的请求参数。
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("根据确认结果生成 indexSelection 的请求参数")
|
||||
public class BuildIndexSelectionRequest {
|
||||
|
||||
/** 接口返回的确认模型数据。 */
|
||||
@ApiModelProperty("接口返回的确认模型数据")
|
||||
private List<IndexConfirmGroupRequest> confirmData = new ArrayList<IndexConfirmGroupRequest>();
|
||||
|
||||
/** 前端最终确认后的选择结果。 */
|
||||
@ApiModelProperty("前端最终确认后的选择结果")
|
||||
private List<ConfirmedIndexGroupRequest> confirmedData = new ArrayList<ConfirmedIndexGroupRequest>();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.param;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 前端提交的确认分组结果。
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("前端提交的确认分组结果")
|
||||
public class ConfirmedIndexGroupRequest {
|
||||
|
||||
/** 分组唯一键。 */
|
||||
@ApiModelProperty("分组唯一键")
|
||||
private String groupKey;
|
||||
|
||||
/** 当前分组下按 label 汇总后的确认项。 */
|
||||
@ApiModelProperty("当前分组下按 label 汇总后的确认项")
|
||||
private List<ConfirmedLabelItemRequest> labelItems = new ArrayList<ConfirmedLabelItemRequest>();
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.param;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 前端提交的单个 label 确认结果。
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("前端提交的单个 label 确认结果")
|
||||
public class ConfirmedLabelItemRequest {
|
||||
|
||||
/** 模板标签。 */
|
||||
@ApiModelProperty("模板标签")
|
||||
private String label;
|
||||
|
||||
/** 是否启用当前配置。 */
|
||||
@ApiModelProperty("是否启用当前配置")
|
||||
private boolean enabled;
|
||||
|
||||
/** 当前 label 选中的 lnInst。 */
|
||||
@ApiModelProperty("当前 label 选中的 lnInst")
|
||||
private String lnInst;
|
||||
}
|
||||
@@ -1,38 +1,43 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.param;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 候选接口请求体。
|
||||
*
|
||||
* 当前主要承载输出版本、作者、落盘选项等基础参数。
|
||||
* 为兼容旧调用,仍保留 indexSelection 字段,但候选接口本身不依赖该字段。
|
||||
* 上传 ICD 后直接生成映射的请求参数。
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("上传 ICD 后直接生成映射的请求参数")
|
||||
public class GenerateMappingFromIcdRequest {
|
||||
|
||||
/** 输出版本号。为空时后端默认补当天日期。 */
|
||||
/** 映射版本号。 */
|
||||
@ApiModelProperty("映射版本号,空时默认使用当天日期")
|
||||
private String version;
|
||||
|
||||
/** 作者。为空时使用模块默认作者。 */
|
||||
/** 映射作者。 */
|
||||
@ApiModelProperty("映射作者,空时使用模块默认作者")
|
||||
private String author;
|
||||
|
||||
/** 是否保存到磁盘。 */
|
||||
/** 是否落盘。 */
|
||||
@ApiModelProperty("是否将生成结果落盘保存")
|
||||
private boolean saveToDisk;
|
||||
|
||||
/** 是否返回格式化 JSON。 */
|
||||
/** 是否格式化 JSON。 */
|
||||
@ApiModelProperty("是否返回格式化后的 JSON")
|
||||
private boolean prettyJson;
|
||||
|
||||
/** 输出目录。saveToDisk=true 时才会用到。 */
|
||||
/** 输出目录。 */
|
||||
@ApiModelProperty("输出目录,仅在 saveToDisk=true 时生效")
|
||||
private String outputDir;
|
||||
|
||||
/**
|
||||
* 兼容保留的索引选择结果。
|
||||
*
|
||||
* 当前候选接口会直接返回 indexCandidates 和 icdDocument;
|
||||
* 正式提交时请改用 get-mms-json 接口。
|
||||
* 兼容保留的索引绑定结果。
|
||||
* 正式提交流程建议改用 get-mms-json 接口。
|
||||
*/
|
||||
@ApiModelProperty("兼容保留的索引绑定结果,正式提交建议改用 get-mms-json 接口")
|
||||
private List<IndexSelectionGroupRequest> indexSelection = new ArrayList<IndexSelectionGroupRequest>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,29 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.param;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 单条索引绑定请求。
|
||||
*
|
||||
* 一条绑定只表达一个最小关系:
|
||||
* 某个报告 reportName 下,使用某个标签 label 与某个 lnInst 数字做绑定。
|
||||
* 单条索引绑定请求项。
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("单条索引绑定请求项")
|
||||
public class IndexBindingRequest {
|
||||
|
||||
/** 绑定发生在哪个报告上,例如 brcbStHarm。 */
|
||||
/** 报告名称。 */
|
||||
@ApiModelProperty("报告名称")
|
||||
private String reportName;
|
||||
|
||||
/** 绑定发生在哪个数据集上,例如 dsStHarm。 */
|
||||
/** 数据集名称。 */
|
||||
@ApiModelProperty("数据集名称")
|
||||
private String dataSetName;
|
||||
|
||||
/** 业务标签,例如最大值、最小值、实时数据。 */
|
||||
/** 模板标签。 */
|
||||
@ApiModelProperty("模板标签")
|
||||
private String label;
|
||||
|
||||
/** 当前标签最终绑定到的 lnInst 数字,例如 1、2、3。 */
|
||||
/** 最终绑定的 lnInst 值。 */
|
||||
@ApiModelProperty("最终绑定的 lnInst 值")
|
||||
private String lnInst;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.param;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 索引候选中的单个报告请求项。
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("索引候选中的单个报告请求项")
|
||||
public class IndexCandidateReportItemRequest {
|
||||
|
||||
/** 报告名称。 */
|
||||
@ApiModelProperty("报告名称")
|
||||
private String reportName;
|
||||
|
||||
/** 数据集名称。 */
|
||||
@ApiModelProperty("数据集名称")
|
||||
private String dataSetName;
|
||||
|
||||
/** 报告描述。 */
|
||||
@ApiModelProperty("报告描述")
|
||||
private String reportDesc;
|
||||
|
||||
/** 当前报告允许选择的 lnInst 值列表。 */
|
||||
@ApiModelProperty("当前报告允许选择的 lnInst 值列表")
|
||||
private List<String> availableLnInstValues = new ArrayList<String>();
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.param;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 索引候选分组请求参数。
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("索引候选分组请求参数")
|
||||
public class IndexCandidateRequest {
|
||||
|
||||
/** 分组唯一键。 */
|
||||
@ApiModelProperty("分组唯一键")
|
||||
private String groupKey;
|
||||
|
||||
/** 分组中文描述。 */
|
||||
@ApiModelProperty("分组中文描述")
|
||||
private String groupDesc;
|
||||
|
||||
/** 当前分组包含的报告数量。 */
|
||||
@ApiModelProperty("当前分组包含的报告数量")
|
||||
private int reportCount;
|
||||
|
||||
/** 当前分组展示的模板标签列表。 */
|
||||
@ApiModelProperty("当前分组展示的模板标签列表")
|
||||
private List<String> templateLabels = new ArrayList<String>();
|
||||
|
||||
/** 当前分组下的报告候选列表。 */
|
||||
@ApiModelProperty("当前分组下的报告候选列表")
|
||||
private List<IndexCandidateReportItemRequest> reports = new ArrayList<IndexCandidateReportItemRequest>();
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.param;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 索引确认分组请求参数。
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("索引确认分组请求参数")
|
||||
public class IndexConfirmGroupRequest {
|
||||
|
||||
/** 分组唯一键。 */
|
||||
@ApiModelProperty("分组唯一键")
|
||||
private String groupKey;
|
||||
|
||||
/** 分组中文描述。 */
|
||||
@ApiModelProperty("分组中文描述")
|
||||
private String groupDesc;
|
||||
|
||||
/** 当前分组下按 label 聚合后的确认项。 */
|
||||
@ApiModelProperty("当前分组下按 label 聚合后的确认项")
|
||||
private List<IndexConfirmLabelItemRequest> labelItems = new ArrayList<IndexConfirmLabelItemRequest>();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.param;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 索引确认模型中的单个 label 请求项。
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("索引确认模型中的单个 label 请求项")
|
||||
public class IndexConfirmLabelItemRequest {
|
||||
|
||||
/** 模板标签。 */
|
||||
@ApiModelProperty("模板标签")
|
||||
private String label;
|
||||
|
||||
/** 是否必配。 */
|
||||
@ApiModelProperty("是否必配")
|
||||
private boolean required;
|
||||
|
||||
/** 是否支持一次配置后展开到多个报告。 */
|
||||
@ApiModelProperty("是否支持一次配置后展开到多个报告")
|
||||
private boolean configurableOnce;
|
||||
|
||||
/** 所有目标报告共同支持的 lnInst 候选值。 */
|
||||
@ApiModelProperty("所有目标报告共同支持的 lnInst 候选值")
|
||||
private List<String> commonLnInstValues = new ArrayList<String>();
|
||||
|
||||
/** 候选值唯一时的默认 lnInst。 */
|
||||
@ApiModelProperty("候选值唯一时的默认 lnInst")
|
||||
private String defaultLnInst;
|
||||
|
||||
/** 当前 label 影响的目标报告列表。 */
|
||||
@ApiModelProperty("当前 label 影响的目标报告列表")
|
||||
private List<IndexConfirmTargetRequest> targets = new ArrayList<IndexConfirmTargetRequest>();
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.param;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 索引确认模型中的目标报告请求项。
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("索引确认模型中的目标报告请求项")
|
||||
public class IndexConfirmTargetRequest {
|
||||
|
||||
/** 报告名称。 */
|
||||
@ApiModelProperty("报告名称")
|
||||
private String reportName;
|
||||
|
||||
/** 数据集名称。 */
|
||||
@ApiModelProperty("数据集名称")
|
||||
private String dataSetName;
|
||||
|
||||
/** 报告描述。 */
|
||||
@ApiModelProperty("报告描述")
|
||||
private String reportDesc;
|
||||
|
||||
/** 当前目标报告可接受的 lnInst 列表。 */
|
||||
@ApiModelProperty("当前目标报告可接受的 lnInst 列表")
|
||||
private List<String> availableLnInstValues = new ArrayList<String>();
|
||||
}
|
||||
@@ -1,28 +1,28 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.param;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 单个业务分组的索引选择请求。
|
||||
*
|
||||
* 用于回传某个业务分组下,前端最终确认的多条绑定关系。
|
||||
* 单个业务分组的索引选择请求参数。
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("单个业务分组的索引选择请求参数")
|
||||
public class IndexSelectionGroupRequest {
|
||||
|
||||
/**
|
||||
* 分组唯一键。
|
||||
*
|
||||
* 该值由后端在 NEED_INDEX_SELECTION 场景返回,前端应原样回传,
|
||||
* 避免仅依赖中文描述做匹配。
|
||||
*/
|
||||
/** 分组唯一键。 */
|
||||
@ApiModelProperty("分组唯一键,需原样回传后端返回值")
|
||||
private String groupKey;
|
||||
|
||||
/** 分组中文描述,例如“实时数据”“统计数据”。 */
|
||||
/** 分组中文描述。 */
|
||||
@ApiModelProperty("分组中文描述")
|
||||
private String groupDesc;
|
||||
|
||||
/** 当前业务分组下,用户最终确认的绑定关系。 */
|
||||
/** 当前分组最终确认的绑定关系。 */
|
||||
@ApiModelProperty("当前分组最终确认的绑定关系")
|
||||
private List<IndexBindingRequest> bindings = new ArrayList<IndexBindingRequest>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,18 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.param;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
|
||||
/**
|
||||
* JSON 转 XML 请求参数。
|
||||
* MMS JSON 转 XML 的请求参数。
|
||||
*/
|
||||
@ApiModel("MMS JSON 转 XML 的请求参数")
|
||||
public class JsonToXmlRequest {
|
||||
|
||||
/**
|
||||
* MMS 映射 JSON 字符串。
|
||||
* 由 getIcdMmsJson 接口返回的 mappingJson 字段提供。
|
||||
*/
|
||||
/** MMS 映射 JSON 字符串。 */
|
||||
@ApiModelProperty(value = "MMS 映射 JSON 字符串", required = true)
|
||||
private String mappingJson;
|
||||
|
||||
/**
|
||||
* 索引选择结果(用于重建索引映射配置)。
|
||||
* 如果提供了 indexSelection,则会重新构建索引映射;
|
||||
* 如果为空,则使用默认的索引映射配置。
|
||||
*/
|
||||
|
||||
|
||||
public String getMappingJson() {
|
||||
return mappingJson;
|
||||
}
|
||||
@@ -27,6 +20,4 @@ public class JsonToXmlRequest {
|
||||
public void setMappingJson(String mappingJson) {
|
||||
this.mappingJson = mappingJson;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,37 +1,45 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.param;
|
||||
|
||||
import lombok.Data;
|
||||
import com.njcn.gather.icd.mapping.pojo.bo.icd.IcdDocument;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 提交索引绑定并生成映射的请求体。
|
||||
*
|
||||
* 第二个接口不再重复上传 ICD 文件,而是直接接收前端确认或修改后的 ICD 解析结果。
|
||||
* 提交索引绑定并生成 MMS JSON 的请求参数。
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("提交索引绑定并生成 MMS JSON 的请求参数")
|
||||
public class SubmitIndexSelectionRequest {
|
||||
|
||||
/** 前端基于候选接口返回值确认或修改后的 ICD 解析结果。 */
|
||||
/** ICD 解析结果。 */
|
||||
@ApiModelProperty("ICD 解析结果,通常来自候选接口返回")
|
||||
private IcdDocument icdDocument;
|
||||
|
||||
/** 输出版本号。为空时后端默认补当天日期。 */
|
||||
/** 映射版本号。 */
|
||||
@ApiModelProperty("映射版本号,空时默认使用当天日期")
|
||||
private String version;
|
||||
|
||||
/** 作者。为空时使用模块默认作者。 */
|
||||
/** 映射作者。 */
|
||||
@ApiModelProperty("映射作者,空时使用模块默认作者")
|
||||
private String author;
|
||||
|
||||
/** 是否保存到磁盘。 */
|
||||
/** 是否落盘。 */
|
||||
@ApiModelProperty("是否将生成结果落盘保存")
|
||||
private boolean saveToDisk;
|
||||
|
||||
/** 是否返回格式化 JSON。 */
|
||||
/** 是否格式化 JSON。 */
|
||||
@ApiModelProperty("是否返回格式化后的 JSON")
|
||||
private boolean prettyJson;
|
||||
|
||||
/** 输出目录。saveToDisk=true 时才会用到。 */
|
||||
/** 输出目录。 */
|
||||
@ApiModelProperty("输出目录,仅在 saveToDisk=true 时生效")
|
||||
private String outputDir;
|
||||
|
||||
/** 用户最终确认的索引绑定关系。 */
|
||||
@ApiModelProperty("用户最终确认的索引绑定关系")
|
||||
private List<IndexSelectionGroupRequest> indexSelection = new ArrayList<IndexSelectionGroupRequest>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +1,47 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.vo;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.njcn.gather.icd.mapping.pojo.enums.GenerateStatus;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
// 手动写getter/setter,避免Lombok依赖问题
|
||||
/**
|
||||
* MMS JSON 转 XML 的响应。
|
||||
*/
|
||||
@Data
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
@ApiModel("MMS JSON 转 XML 的响应")
|
||||
public class IcdToXmlResponse {
|
||||
private GenerateStatus status;
|
||||
private String message;
|
||||
private String iedName;
|
||||
private String ldInst;
|
||||
private String savedPath;
|
||||
private MappingDocumentResponse mappingDocument;
|
||||
private List<IndexCandidateResponse> indexCandidates = new ArrayList<IndexCandidateResponse>();
|
||||
private List<String> problems = new ArrayList<String>();
|
||||
public GenerateStatus getStatus() { return status; }
|
||||
public void setStatus(GenerateStatus status) { this.status = status; }
|
||||
public String getMessage() { return message; }
|
||||
public void setMessage(String message) { this.message = message; }
|
||||
public String getIedName() { return iedName; }
|
||||
public void setIedName(String iedName) { this.iedName = iedName; }
|
||||
public String getLdInst() { return ldInst; }
|
||||
public void setLdInst(String ldInst) { this.ldInst = ldInst; }
|
||||
|
||||
public String getSavedPath() { return savedPath; }
|
||||
public void setSavedPath(String savedPath) { this.savedPath = savedPath; }
|
||||
public MappingDocumentResponse getMappingDocument() { return mappingDocument; }
|
||||
public void setMappingDocument(MappingDocumentResponse mappingDocument) { this.mappingDocument = mappingDocument; }
|
||||
public List<IndexCandidateResponse> getIndexCandidates() { return indexCandidates; }
|
||||
public void setIndexCandidates(List<IndexCandidateResponse> indexCandidates) { this.indexCandidates = indexCandidates; }
|
||||
public List<String> getProblems() { return problems; }
|
||||
public void setProblems(List<String> problems) { this.problems = problems; }
|
||||
}
|
||||
@ApiModelProperty("本次接口处理状态")
|
||||
private GenerateStatus status;
|
||||
|
||||
@ApiModelProperty("状态说明或错误提示")
|
||||
private String message;
|
||||
|
||||
@ApiModelProperty("接口方法描述")
|
||||
private String methodDescribe;
|
||||
|
||||
@ApiModelProperty("IED 名称")
|
||||
private String iedName;
|
||||
|
||||
@ApiModelProperty("逻辑设备实例名")
|
||||
private String ldInst;
|
||||
|
||||
@ApiModelProperty("生成后的 XML 文件展示容器")
|
||||
private XmlFileResponse xmlFile;
|
||||
|
||||
@ApiModelProperty("生成后的映射文档摘要")
|
||||
private MappingDocumentResponse mappingDocument;
|
||||
|
||||
@ApiModelProperty("索引候选分组,存在待确认场景时返回")
|
||||
private List<IndexCandidateResponse> indexCandidates = new ArrayList<IndexCandidateResponse>();
|
||||
|
||||
@ApiModelProperty("处理过程中发现的问题列表")
|
||||
private List<String> problems = new ArrayList<String>();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 单条索引绑定响应项。
|
||||
*/
|
||||
@Data
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
@ApiModel("单条索引绑定响应项")
|
||||
public class IndexBindingResponse {
|
||||
|
||||
/** 报告名称。 */
|
||||
@ApiModelProperty("报告名称")
|
||||
private String reportName;
|
||||
|
||||
/** 数据集名称。 */
|
||||
@ApiModelProperty("数据集名称")
|
||||
private String dataSetName;
|
||||
|
||||
/** 模板标签。 */
|
||||
@ApiModelProperty("模板标签")
|
||||
private String label;
|
||||
|
||||
/** 当前标签对应的 lnInst。 */
|
||||
@ApiModelProperty("当前标签对应的 lnInst")
|
||||
private String lnInst;
|
||||
}
|
||||
@@ -1,27 +1,34 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 业务分组下的单个报告候选响应。
|
||||
* 索引候选中的单个报告响应项。
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
@Data
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
@ApiModel("索引候选中的单个报告响应项")
|
||||
public class IndexCandidateReportItemResponse {
|
||||
|
||||
/** 报告名称。 */
|
||||
@ApiModelProperty("报告名称")
|
||||
private String reportName;
|
||||
|
||||
/** 数据集名称。 */
|
||||
@ApiModelProperty("数据集名称")
|
||||
private String dataSetName;
|
||||
|
||||
/** 报告描述。 */
|
||||
@ApiModelProperty("报告描述")
|
||||
private String reportDesc;
|
||||
|
||||
/** 当前报告可选的 `lnInst` 数值。 */
|
||||
/** 当前报告可选的 lnInst 值列表。 */
|
||||
@ApiModelProperty("当前报告可选的 lnInst 值列表")
|
||||
private List<String> availableLnInstValues = new ArrayList<String>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,38 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 索引候选响应对象。
|
||||
*
|
||||
* 一个候选对应一个业务分组,分组下可包含多个报告,
|
||||
* 前端据此完成模板标签与 `lnInst` 的人工绑定。
|
||||
* 索引候选分组响应。
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
@Data
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
@ApiModel("索引候选分组响应")
|
||||
public class IndexCandidateResponse {
|
||||
|
||||
/** 分组唯一键。 */
|
||||
@ApiModelProperty("分组唯一键")
|
||||
private String groupKey;
|
||||
|
||||
/** 分组中文描述。 */
|
||||
@ApiModelProperty("分组中文描述")
|
||||
private String groupDesc;
|
||||
|
||||
/** 当前分组包含的报告数。 */
|
||||
/** 当前分组包含的报告数量。 */
|
||||
@ApiModelProperty("当前分组包含的报告数量")
|
||||
private int reportCount;
|
||||
|
||||
/** 模板里配置的可选标签。 */
|
||||
/** 模板中配置的可选标签。 */
|
||||
@ApiModelProperty("模板中配置的可选标签")
|
||||
private List<String> templateLabels = new ArrayList<String>();
|
||||
|
||||
/** 当前分组下的报告候选列表。 */
|
||||
@ApiModelProperty("当前分组下的报告候选列表")
|
||||
private List<IndexCandidateReportItemResponse> reports = new ArrayList<IndexCandidateReportItemResponse>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 索引确认分组响应。
|
||||
*/
|
||||
@Data
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
@ApiModel("索引确认分组响应")
|
||||
public class IndexConfirmGroupResponse {
|
||||
|
||||
/** 分组唯一键。 */
|
||||
@ApiModelProperty("分组唯一键")
|
||||
private String groupKey;
|
||||
|
||||
/** 分组中文描述。 */
|
||||
@ApiModelProperty("分组中文描述")
|
||||
private String groupDesc;
|
||||
|
||||
/** 当前分组下按 label 聚合后的确认项。 */
|
||||
@ApiModelProperty("当前分组下按 label 聚合后的确认项")
|
||||
private List<IndexConfirmLabelItemResponse> labelItems = new ArrayList<IndexConfirmLabelItemResponse>();
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 索引确认模型中的单个 label 响应项。
|
||||
*/
|
||||
@Data
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
@ApiModel("索引确认模型中的单个 label 响应项")
|
||||
public class IndexConfirmLabelItemResponse {
|
||||
|
||||
/** 模板标签。 */
|
||||
@ApiModelProperty("模板标签")
|
||||
private String label;
|
||||
|
||||
/** 是否必配。 */
|
||||
@ApiModelProperty("是否必配")
|
||||
private boolean required;
|
||||
|
||||
/** 是否支持一次配置后展开到多个报告。 */
|
||||
@ApiModelProperty("是否支持一次配置后展开到多个报告")
|
||||
private boolean configurableOnce;
|
||||
|
||||
/** 所有目标报告共同支持的 lnInst 候选值。 */
|
||||
@ApiModelProperty("所有目标报告共同支持的 lnInst 候选值")
|
||||
private List<String> commonLnInstValues = new ArrayList<String>();
|
||||
|
||||
/** 候选值唯一时的默认 lnInst。 */
|
||||
@ApiModelProperty("候选值唯一时的默认 lnInst")
|
||||
private String defaultLnInst;
|
||||
|
||||
/** 当前 label 影响的全部目标报告。 */
|
||||
@ApiModelProperty("当前 label 影响的全部目标报告")
|
||||
private List<IndexConfirmTargetResponse> targets = new ArrayList<IndexConfirmTargetResponse>();
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 索引确认模型中的目标报告响应项。
|
||||
*/
|
||||
@Data
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
@ApiModel("索引确认模型中的目标报告响应项")
|
||||
public class IndexConfirmTargetResponse {
|
||||
|
||||
/** 报告名称。 */
|
||||
@ApiModelProperty("报告名称")
|
||||
private String reportName;
|
||||
|
||||
/** 数据集名称。 */
|
||||
@ApiModelProperty("数据集名称")
|
||||
private String dataSetName;
|
||||
|
||||
/** 报告描述。 */
|
||||
@ApiModelProperty("报告描述")
|
||||
private String reportDesc;
|
||||
|
||||
/** 当前目标报告可接受的 lnInst 列表。 */
|
||||
@ApiModelProperty("当前目标报告可接受的 lnInst 列表")
|
||||
private List<String> availableLnInstValues = new ArrayList<String>();
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 生成后的索引选择分组响应。
|
||||
*/
|
||||
@Data
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
@ApiModel("生成后的索引选择分组响应")
|
||||
public class IndexSelectionGroupResponse {
|
||||
|
||||
/** 分组唯一键。 */
|
||||
@ApiModelProperty("分组唯一键")
|
||||
private String groupKey;
|
||||
|
||||
/** 分组中文描述。 */
|
||||
@ApiModelProperty("分组中文描述")
|
||||
private String groupDesc;
|
||||
|
||||
/** 当前分组最终生成的绑定关系。 */
|
||||
@ApiModelProperty("当前分组最终生成的绑定关系")
|
||||
private List<IndexBindingResponse> bindings = new ArrayList<IndexBindingResponse>();
|
||||
}
|
||||
@@ -1,28 +1,37 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 映射文档摘要响应。
|
||||
*
|
||||
* 用于返回最终映射结果中的关键信息摘要。
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("映射文档摘要响应")
|
||||
public class MappingDocumentResponse {
|
||||
|
||||
/** 映射文档版本。 */
|
||||
@ApiModelProperty("映射文档版本")
|
||||
private String version;
|
||||
|
||||
/** 映射文档作者。 */
|
||||
@ApiModelProperty("映射文档作者")
|
||||
private String author;
|
||||
|
||||
/** 输出 JSON 中的 IED。 */
|
||||
@ApiModelProperty("输出 JSON 中的 IED")
|
||||
private String ied;
|
||||
|
||||
/** 输出 JSON 中的 LD。 */
|
||||
@ApiModelProperty("输出 JSON 中的 LD")
|
||||
private String ld;
|
||||
|
||||
/** ReportMap 条目数量。 */
|
||||
@ApiModelProperty("ReportMap 条目数量")
|
||||
private int reportCount;
|
||||
|
||||
/** DataSetList 分组数量。 */
|
||||
@ApiModelProperty("DataSetList 分组数量")
|
||||
private int dataSetCount;
|
||||
}
|
||||
|
||||
@@ -1,39 +1,53 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.njcn.gather.icd.mapping.pojo.bo.icd.IcdDocument;
|
||||
import com.njcn.gather.icd.mapping.pojo.bo.mapping.MappingDocument;
|
||||
import com.njcn.gather.icd.mapping.pojo.enums.GenerateStatus;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* ICD 映射接口统一响应。
|
||||
*
|
||||
* 按接口阶段仅返回当前场景必需字段;空字段和空集合不参与序列化。
|
||||
* ICD 映射统一响应。
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
@Data
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
@ApiModel("ICD 映射统一响应")
|
||||
public class MappingTaskResponse {
|
||||
|
||||
/** 本次接口处理状态。 */
|
||||
@ApiModelProperty("本次接口处理状态")
|
||||
private GenerateStatus status;
|
||||
|
||||
/** 状态说明或错误提示。 */
|
||||
@ApiModelProperty("状态说明或错误提示")
|
||||
private String message;
|
||||
|
||||
/** 候选接口或需要重新选择索引时返回的 ICD 解析结果。 */
|
||||
/** ICD 解析结果。 */
|
||||
@ApiModelProperty("ICD 解析结果,在需要确认索引时返回")
|
||||
private IcdDocument icdDocument;
|
||||
|
||||
/** 正式生成成功后的完整映射 JSON。 */
|
||||
@ApiModelProperty("正式生成成功后的完整映射 JSON")
|
||||
private String mappingJson;
|
||||
|
||||
/** 生成文件落盘后的绝对路径。 */
|
||||
/** 正式生成成功后的结构化映射文档。 */
|
||||
@ApiModelProperty("正式生成成功后的结构化映射文档")
|
||||
private MappingDocument mappingDocument;
|
||||
|
||||
/** 落盘后的绝对路径。 */
|
||||
@ApiModelProperty("落盘后的绝对路径")
|
||||
private String savedPath;
|
||||
|
||||
/** 待绑定状态下返回的索引候选分组。 */
|
||||
@ApiModelProperty("待绑定状态下返回的索引候选分组")
|
||||
private List<IndexCandidateResponse> indexCandidates = new ArrayList<IndexCandidateResponse>();
|
||||
|
||||
/** 模板校验、候选分析或绑定校验问题。 */
|
||||
@ApiModelProperty("模板校验、候选分析或绑定校验问题")
|
||||
private List<String> problems = new ArrayList<String>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.njcn.gather.icd.mapping.pojo.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* XML 文件展示容器。
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("XML 文件展示容器")
|
||||
public class XmlFileResponse {
|
||||
|
||||
/** XML 文件名。 */
|
||||
@ApiModelProperty("XML 文件名")
|
||||
private String fileName;
|
||||
|
||||
/** 文件内容类型。 */
|
||||
@ApiModelProperty("文件内容类型")
|
||||
private String contentType;
|
||||
|
||||
/** 文件编码。 */
|
||||
@ApiModelProperty("文件编码")
|
||||
private String encoding;
|
||||
|
||||
/** XML 文件内容。 */
|
||||
@ApiModelProperty("XML 文件内容")
|
||||
private String content;
|
||||
}
|
||||
@@ -1,7 +1,14 @@
|
||||
package com.njcn.gather.icd.mapping.service.impl;
|
||||
|
||||
|
||||
import com.njcn.gather.icd.mapping.component.*;
|
||||
import com.njcn.gather.icd.mapping.component.DefaultTemplateLoader;
|
||||
import com.njcn.gather.icd.mapping.component.IcdParserService;
|
||||
import com.njcn.gather.icd.mapping.component.IcdToXmlMappingService;
|
||||
import com.njcn.gather.icd.mapping.component.IndexAnalysisService;
|
||||
import com.njcn.gather.icd.mapping.component.IndexValidationService;
|
||||
import com.njcn.gather.icd.mapping.component.JsonToXmlConversionService;
|
||||
import com.njcn.gather.icd.mapping.component.MappingDocumentSerializer;
|
||||
import com.njcn.gather.icd.mapping.component.MappingGenerationService;
|
||||
import com.njcn.gather.icd.mapping.component.RuleBasedXmlMappingService;
|
||||
import com.njcn.gather.icd.mapping.pojo.bo.IcdToXmlGenerateResult;
|
||||
import com.njcn.gather.icd.mapping.pojo.bo.analysis.IndexAnalysis;
|
||||
import com.njcn.gather.icd.mapping.pojo.bo.analysis.ValidationResult;
|
||||
@@ -9,173 +16,292 @@ import com.njcn.gather.icd.mapping.pojo.bo.icd.IcdDocument;
|
||||
import com.njcn.gather.icd.mapping.pojo.bo.mapping.MappingDocument;
|
||||
import com.njcn.gather.icd.mapping.pojo.bo.template.DefaultTemplate;
|
||||
import com.njcn.gather.icd.mapping.pojo.dto.IcdToXmlGenerateCommand;
|
||||
import com.njcn.gather.icd.mapping.pojo.dto.IndexSelectionGroupCommand;
|
||||
import com.njcn.gather.icd.mapping.pojo.enums.GenerateStatus;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* ICD/XML 生成任务编排服务。
|
||||
*
|
||||
* 负责组织 ICD 到 XML、MMS JSON 到 XML 两类转换链路,避免 Controller 关注模板、规则和异常处理细节。
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class IcdToXmlTaskAppService {
|
||||
|
||||
/** ICD 转 XML 阶段名称。 */
|
||||
private static final String ICD_TO_XML_TASK_NAME = "ICD 转 XML";
|
||||
/** JSON 转 XML 阶段名称。 */
|
||||
private static final String JSON_TO_XML_TASK_NAME = "XML 生成";
|
||||
/** 缺少索引绑定提示。 */
|
||||
private static final String INDEX_SELECTION_MISSING_MESSAGE = "索引配置缺失或不合法,请根据候选信息完成标签与数字索引的绑定后重新提交";
|
||||
/** 映射生成成功提示。 */
|
||||
private static final String MAPPING_GENERATE_SUCCESS_MESSAGE = "映射生成成功";
|
||||
/** XML 生成成功提示。 */
|
||||
private static final String XML_GENERATE_SUCCESS_MESSAGE = "XML 生成成功";
|
||||
/** 空 JSON 提示。 */
|
||||
private static final String MAPPING_JSON_EMPTY_MESSAGE = "MMS映射JSON不能为空";
|
||||
/** 缺少默认 XML 模板提示。 */
|
||||
private static final String DEFAULT_XML_MISSING_MESSAGE = "缺少默认xml配置文件";
|
||||
/** 缺少默认规则文件提示。 */
|
||||
private static final String DEFAULT_RULE_MISSING_MESSAGE = "缺少默认规则配置文件";
|
||||
|
||||
/** ICD/SCL 文件解析服务。 */
|
||||
private final IcdParserService icdParserService;
|
||||
/** DefaultCfg.txt 默认模板加载器。 */
|
||||
private final DefaultTemplateLoader defaultTemplateLoader;
|
||||
/** 根据 ICD 和模板生成前端可选索引候选。 */
|
||||
private final IndexAnalysisService indexAnalysisService;
|
||||
/** 校验前端回传的标签与 lnInst 绑定关系。 */
|
||||
private final IndexValidationService indexValidationService;
|
||||
/** 根据有效绑定关系生成最终 MappingDocument。 */
|
||||
private final MappingGenerationService mappingGenerationService;
|
||||
/** XML 模板和规则文件加载服务。 */
|
||||
private final RuleBasedXmlMappingService ruleBasedXmlMappingService;
|
||||
/** 将 MappingDocument 序列化为 JSON。 */
|
||||
private final MappingDocumentSerializer mappingDocumentSerializer;
|
||||
private final FileStorageService fileStorageService;
|
||||
/** 根据索引绑定关系重建 XML 规则中的实例索引。 */
|
||||
private final IcdToXmlMappingService icdToXmlMappingService;
|
||||
/** 将 MMS JSON 中间态转换为 XML 内容。 */
|
||||
private final JsonToXmlConversionService jsonToXmlConversionService;
|
||||
|
||||
public IcdToXmlTaskAppService(IcdParserService icdParserService,
|
||||
DefaultTemplateLoader defaultTemplateLoader,
|
||||
IndexAnalysisService indexAnalysisService,
|
||||
IndexValidationService indexValidationService,
|
||||
MappingGenerationService mappingGenerationService,
|
||||
RuleBasedXmlMappingService ruleBasedXmlMappingService,
|
||||
MappingDocumentSerializer mappingDocumentSerializer,
|
||||
FileStorageService fileStorageService,
|
||||
IcdToXmlMappingService icdToXmlMappingService,
|
||||
JsonToXmlConversionService jsonToXmlConversionService) {
|
||||
this.icdParserService = icdParserService;
|
||||
this.defaultTemplateLoader = defaultTemplateLoader;
|
||||
this.indexAnalysisService = indexAnalysisService;
|
||||
this.indexValidationService = indexValidationService;
|
||||
this.mappingGenerationService = mappingGenerationService;
|
||||
this.ruleBasedXmlMappingService = ruleBasedXmlMappingService;
|
||||
this.mappingDocumentSerializer = mappingDocumentSerializer;
|
||||
this.fileStorageService = fileStorageService;
|
||||
this.icdToXmlMappingService = icdToXmlMappingService;
|
||||
this.jsonToXmlConversionService = jsonToXmlConversionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析 ICD 并按索引绑定关系直接生成 XML 内容。
|
||||
*/
|
||||
public IcdToXmlGenerateResult generateFromIcd(IcdToXmlGenerateCommand command) {
|
||||
IcdToXmlGenerateResult result = new IcdToXmlGenerateResult();
|
||||
try {
|
||||
// ========== 第一步:ICD → JSON ==========
|
||||
|
||||
// 1. 解析 ICD
|
||||
IcdDocument icdDocument = icdParserService.parse(command.getFileBytes(), command.getFileName());
|
||||
result.setIedName(icdDocument.getIedName());
|
||||
result.setLdInst(icdDocument.getLdInst());
|
||||
return executeTask(ICD_TO_XML_TASK_NAME, result -> {
|
||||
IcdToXmlTaskContext context = buildTaskContext(command, result);
|
||||
|
||||
// 2. 加载 DefaultCfg.txt和默认配置
|
||||
//DefaultTemplate template = defaultTemplateLoader.loadDefaultTemplateToXml();
|
||||
DefaultTemplate template = defaultTemplateLoader.load();
|
||||
result.getProblems().addAll(template.verify());
|
||||
|
||||
InputStream templateStream = ruleBasedXmlMappingService.loadDefaultXmlFile();
|
||||
if(templateStream==null){result.getProblems().add("缺少默认xml配置文件");}
|
||||
List<InputStream> ruleStreams = ruleBasedXmlMappingService.loadDefaultRuleFile();
|
||||
if(ruleStreams==null){result.getProblems().add("缺少默认规则配置文件");}
|
||||
|
||||
|
||||
// 3. 分析索引候选
|
||||
IndexAnalysis indexAnalysis = indexAnalysisService.analyze(icdDocument, template);
|
||||
result.setIndexAnalysis(indexAnalysis);
|
||||
result.getProblems().addAll(indexAnalysis.getProblems());
|
||||
|
||||
// 4. 如果没有提交任何绑定关系,则直接返回待匹配项
|
||||
if (command.getIndexSelection() == null || command.getIndexSelection().isEmpty()) {
|
||||
result.setStatus(GenerateStatus.NEED_INDEX_SELECTION);
|
||||
result.setMessage("索引配置缺失或不合法,请根据候选信息完成标签与数字索引的绑定后重新提交");
|
||||
return result;
|
||||
if (isIndexSelectionEmpty(command.getIndexSelection())) {
|
||||
markNeedIndexSelection(result);
|
||||
return;
|
||||
}
|
||||
|
||||
// 5. 校验用户提交的绑定关系
|
||||
ValidationResult validationResult = indexValidationService.validate(indexAnalysis, command.getIndexSelection());
|
||||
ValidationResult validationResult = indexValidationService.validate(context.indexAnalysis, command.getIndexSelection());
|
||||
if (!validationResult.isValid()) {
|
||||
result.setStatus(GenerateStatus.NEED_INDEX_SELECTION);
|
||||
result.setMessage("索引配置缺失或不合法,请根据候选信息完成标签与数字索引的绑定后重新提交");
|
||||
markNeedIndexSelection(result);
|
||||
result.getProblems().addAll(validationResult.getProblems());
|
||||
return result;
|
||||
return;
|
||||
}
|
||||
|
||||
// 6. 生成正式映射结构(JSON中间态)
|
||||
MappingDocument mappingDocument = mappingGenerationService.generate(
|
||||
icdDocument,
|
||||
template,
|
||||
indexAnalysis,
|
||||
context.icdDocument,
|
||||
context.template,
|
||||
context.indexAnalysis,
|
||||
command.getIndexSelection(),
|
||||
command.getVersion(),
|
||||
command.getAuthor()
|
||||
);
|
||||
result.setMappingDocument(mappingDocument);
|
||||
|
||||
// 7. 序列化为JSON字符串(中间产物)
|
||||
String mappingJson = mappingDocumentSerializer.toPrettyJson(mappingDocument);
|
||||
|
||||
// ========== 第二步:JSON → XML ==========
|
||||
|
||||
// 8. 重新绑定正确索引
|
||||
IcdToXmlMappingService.IndexMappingConfig mappingConfig = icdToXmlMappingService.buildIndexMappingFromSelection(command.getIndexSelection());
|
||||
icdToXmlMappingService.setIndexMapping(mappingConfig);
|
||||
|
||||
// 9. 从JSON转换为XML
|
||||
String xmlPath = jsonToXmlConversionService.convertFromJson(
|
||||
mappingJson,
|
||||
templateStream,
|
||||
ruleStreams,
|
||||
icdToXmlMappingService.getIndexMapping()
|
||||
);
|
||||
result.setSavedPath(xmlPath);
|
||||
String mappingJson = mappingDocumentSerializer.toPrettyJson(mappingDocument);
|
||||
bindIndexMapping(command.getIndexSelection());
|
||||
fillXmlContent(result, mappingJson, loadXmlResources());
|
||||
|
||||
result.setStatus(GenerateStatus.SUCCESS);
|
||||
result.setMessage("映射生成成功");
|
||||
return result;
|
||||
} catch (Exception ex) {
|
||||
result.setStatus(GenerateStatus.FAILED);
|
||||
result.setMessage("映射生成失败:" + ex.getMessage());
|
||||
result.getProblems().add(ex.getMessage());
|
||||
return result;
|
||||
}
|
||||
result.setMessage(MAPPING_GENERATE_SUCCESS_MESSAGE);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接从 JSON 字符串生成 XML 文件。
|
||||
* 直接从 JSON 字符串生成 XML 内容。
|
||||
*
|
||||
* @param mappingJson MMS 映射 JSON 字符串(由 getIcdMmsJson 接口返回)
|
||||
* @return XML 生成结果
|
||||
*/
|
||||
public IcdToXmlGenerateResult generateXmlFromJson(String mappingJson){
|
||||
public IcdToXmlGenerateResult generateXmlFromJson(String mappingJson) {
|
||||
return executeTask(JSON_TO_XML_TASK_NAME, result -> {
|
||||
if (isBlank(mappingJson)) {
|
||||
markFailed(result, JSON_TO_XML_TASK_NAME, MAPPING_JSON_EMPTY_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
fillXmlContent(result, mappingJson, loadXmlResources());
|
||||
result.setStatus(GenerateStatus.SUCCESS);
|
||||
result.setMessage(XML_GENERATE_SUCCESS_MESSAGE);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一包装任务执行结果,避免每个入口重复编写异常兜底逻辑。
|
||||
*/
|
||||
private IcdToXmlGenerateResult executeTask(String taskName, IcdToXmlTaskAction action) {
|
||||
IcdToXmlGenerateResult result = new IcdToXmlGenerateResult();
|
||||
try {
|
||||
// 1. 加载模板和规则文件
|
||||
InputStream templateStream = ruleBasedXmlMappingService.loadDefaultXmlFile();
|
||||
if (templateStream == null) {
|
||||
result.setStatus(GenerateStatus.FAILED);
|
||||
result.getProblems().add("缺少默认xml配置文件");
|
||||
result.setMessage("XML 生成失败:缺少默认xml配置文件");
|
||||
return result;
|
||||
}
|
||||
|
||||
List<InputStream> ruleStreams = ruleBasedXmlMappingService.loadDefaultRuleFile();
|
||||
if (ruleStreams == null) {
|
||||
result.setStatus(GenerateStatus.FAILED);
|
||||
result.getProblems().add("缺少默认规则配置文件");
|
||||
result.setMessage("XML 生成失败:缺少默认规则配置文件");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// 3. 从 JSON 转换为 XML
|
||||
String xmlPath = jsonToXmlConversionService.convertFromJson(
|
||||
mappingJson,
|
||||
templateStream,
|
||||
ruleStreams,
|
||||
icdToXmlMappingService.getIndexMapping()
|
||||
);
|
||||
|
||||
result.setSavedPath(xmlPath);
|
||||
result.setStatus(GenerateStatus.SUCCESS);
|
||||
result.setMessage("XML 生成成功");
|
||||
return result;
|
||||
action.execute(result);
|
||||
} catch (Exception ex) {
|
||||
result.setStatus(GenerateStatus.FAILED);
|
||||
result.setMessage("XML 生成失败:" + ex.getMessage());
|
||||
result.getProblems().add(ex.getMessage());
|
||||
return result;
|
||||
handleTaskFailure(result, taskName, ex);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析 ICD 并补齐模板、索引候选上下文。
|
||||
*/
|
||||
private IcdToXmlTaskContext buildTaskContext(IcdToXmlGenerateCommand command, IcdToXmlGenerateResult result) {
|
||||
IcdDocument icdDocument = icdParserService.parse(command.getFileBytes(), command.getFileName());
|
||||
fillIcdSummary(result, icdDocument);
|
||||
|
||||
DefaultTemplate template = loadTemplate(result);
|
||||
IndexAnalysis indexAnalysis = analyzeIndexCandidates(icdDocument, template, result);
|
||||
result.setIndexAnalysis(indexAnalysis);
|
||||
return new IcdToXmlTaskContext(icdDocument, template, indexAnalysis);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载并校验默认模板。
|
||||
*/
|
||||
private DefaultTemplate loadTemplate(IcdToXmlGenerateResult result) {
|
||||
DefaultTemplate template = defaultTemplateLoader.load();
|
||||
result.getProblems().addAll(template.verify());
|
||||
return template;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分析 ICD 对应的索引候选。
|
||||
*/
|
||||
private IndexAnalysis analyzeIndexCandidates(IcdDocument icdDocument,
|
||||
DefaultTemplate template,
|
||||
IcdToXmlGenerateResult result) {
|
||||
IndexAnalysis indexAnalysis = indexAnalysisService.analyze(icdDocument, template);
|
||||
result.getProblems().addAll(indexAnalysis.getProblems());
|
||||
return indexAnalysis;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载 XML 模板和规则文件。
|
||||
*/
|
||||
private XmlResourceContext loadXmlResources() throws Exception {
|
||||
InputStream templateStream = ruleBasedXmlMappingService.loadDefaultXmlFile();
|
||||
if (templateStream == null) {
|
||||
throw new IllegalArgumentException(DEFAULT_XML_MISSING_MESSAGE);
|
||||
}
|
||||
|
||||
List<InputStream> ruleStreams = ruleBasedXmlMappingService.loadDefaultRuleFile();
|
||||
if (ruleStreams == null) {
|
||||
throw new IllegalArgumentException(DEFAULT_RULE_MISSING_MESSAGE);
|
||||
}
|
||||
|
||||
return new XmlResourceContext(templateStream, ruleStreams);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据索引绑定关系刷新 XML 转换所需的实例索引。
|
||||
*/
|
||||
private void bindIndexMapping(List<IndexSelectionGroupCommand> indexSelection) {
|
||||
IcdToXmlMappingService.IndexMappingConfig mappingConfig = icdToXmlMappingService.buildIndexMappingFromSelection(indexSelection);
|
||||
icdToXmlMappingService.setIndexMapping(mappingConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 MMS JSON 中间态转换为 XML 内容。
|
||||
*/
|
||||
private void fillXmlContent(IcdToXmlGenerateResult result,
|
||||
String mappingJson,
|
||||
XmlResourceContext xmlResourceContext) throws Exception {
|
||||
List<String> methodDescribeList = new ArrayList<>();
|
||||
String xmlContent = jsonToXmlConversionService.buildXmlContentFromJson(
|
||||
mappingJson,
|
||||
xmlResourceContext.templateStream,
|
||||
xmlResourceContext.ruleStreams,
|
||||
icdToXmlMappingService.getIndexMapping(),
|
||||
methodDescribeList
|
||||
);
|
||||
result.setXmlContent(xmlContent);
|
||||
result.setMethodDescribe(String.join("\n", methodDescribeList));
|
||||
}
|
||||
|
||||
/**
|
||||
* 回填响应公共信息。
|
||||
*/
|
||||
private void fillIcdSummary(IcdToXmlGenerateResult result, IcdDocument icdDocument) {
|
||||
result.setIedName(icdDocument.getIedName());
|
||||
result.setLdInst(icdDocument.getLdInst());
|
||||
}
|
||||
|
||||
/**
|
||||
* 标记当前仍需用户重新确认索引绑定。
|
||||
*/
|
||||
private void markNeedIndexSelection(IcdToXmlGenerateResult result) {
|
||||
result.setStatus(GenerateStatus.NEED_INDEX_SELECTION);
|
||||
result.setMessage(INDEX_SELECTION_MISSING_MESSAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 标记可预期的业务失败。
|
||||
*/
|
||||
private void markFailed(IcdToXmlGenerateResult result, String taskName, String errorMessage) {
|
||||
result.setStatus(GenerateStatus.FAILED);
|
||||
result.setMessage(taskName + "失败:" + errorMessage);
|
||||
result.getProblems().add(errorMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一处理任务异常,避免控制层再补失败分支。
|
||||
*/
|
||||
private void handleTaskFailure(IcdToXmlGenerateResult result, String taskName, Exception ex) {
|
||||
log.error("{}失败", taskName, ex);
|
||||
String errorMessage = resolveErrorMessage(ex);
|
||||
markFailed(result, taskName, errorMessage);
|
||||
}
|
||||
|
||||
private boolean isIndexSelectionEmpty(List<IndexSelectionGroupCommand> indexSelection) {
|
||||
return indexSelection == null || indexSelection.isEmpty();
|
||||
}
|
||||
|
||||
private boolean isBlank(String value) {
|
||||
return value == null || value.trim().isEmpty();
|
||||
}
|
||||
|
||||
private String resolveErrorMessage(Exception ex) {
|
||||
if (ex.getMessage() == null || ex.getMessage().trim().isEmpty()) {
|
||||
return ex.getClass().getSimpleName();
|
||||
}
|
||||
return ex.getMessage();
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface IcdToXmlTaskAction {
|
||||
void execute(IcdToXmlGenerateResult result) throws Exception;
|
||||
}
|
||||
|
||||
/**
|
||||
* 供 ICD 转 XML 流程复用的编排上下文。
|
||||
*/
|
||||
private static class IcdToXmlTaskContext {
|
||||
|
||||
private final IcdDocument icdDocument;
|
||||
|
||||
private final DefaultTemplate template;
|
||||
|
||||
private final IndexAnalysis indexAnalysis;
|
||||
|
||||
private IcdToXmlTaskContext(IcdDocument icdDocument, DefaultTemplate template, IndexAnalysis indexAnalysis) {
|
||||
this.icdDocument = icdDocument;
|
||||
this.template = template;
|
||||
this.indexAnalysis = indexAnalysis;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* XML 转换所需的模板和规则资源。
|
||||
*/
|
||||
private static class XmlResourceContext {
|
||||
|
||||
private final InputStream templateStream;
|
||||
|
||||
private final List<InputStream> ruleStreams;
|
||||
|
||||
private XmlResourceContext(InputStream templateStream, List<InputStream> ruleStreams) {
|
||||
this.templateStream = templateStream;
|
||||
this.ruleStreams = ruleStreams;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ import java.util.List;
|
||||
public class GetIcdMmsJsonDebugRunner {
|
||||
|
||||
/** 本地 ICD/SCD 文件路径,运行前请改成真实文件。 */
|
||||
private static final String ICD_FILE_PATH = "D:/temp/demo.icd";
|
||||
private static final String ICD_FILE_PATH = "D:\\Work\\工作资料\\1灿能项目资料\\01自研\\01灿能\\09灿能C端功能\\01需求文档\\灿能工具箱开发\\icd\\PQS882_VX_BJ_1(V111).icd";
|
||||
|
||||
/** 调试时可固定版本号,便于对比输出。 */
|
||||
private static final String VERSION = "20260421";
|
||||
@@ -69,6 +69,7 @@ public class GetIcdMmsJsonDebugRunner {
|
||||
|
||||
MappingTaskResponse firstResponse = debugNeedIndexSelection(mappingTaskService, responseConverter);
|
||||
printResponse("第一次调试:获取索引候选", firstResponse, objectMapper);
|
||||
printIndexCandidatesJson(firstResponse, objectMapper);
|
||||
printIndexCandidateSummary(firstResponse);
|
||||
|
||||
if (!RUN_SECOND_STEP) {
|
||||
@@ -192,6 +193,23 @@ public class GetIcdMmsJsonDebugRunner {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 单独输出 indexCandidates 的 JSON,便于直接复制做第二次调试绑定。
|
||||
*/
|
||||
private static void printIndexCandidatesJson(MappingTaskResponse response, ObjectMapper objectMapper) {
|
||||
try {
|
||||
System.out.println();
|
||||
System.out.println("===== indexCandidates JSON =====");
|
||||
if (response == null) {
|
||||
System.out.println("null");
|
||||
return;
|
||||
}
|
||||
System.out.println(objectMapper.writeValueAsString(response.getIndexCandidates()));
|
||||
} catch (Exception ex) {
|
||||
throw new IllegalArgumentException("print indexCandidates JSON failed: " + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void printResponse(String title, MappingTaskResponse response, ObjectMapper objectMapper) {
|
||||
try {
|
||||
System.out.println();
|
||||
|
||||
Reference in New Issue
Block a user