feat(parse-pqdif): 重构PQDIF文件存储及解析功能
- 引入PqdifFileStorageService组件实现PQDIF原始文件本地存储 - 修改application.yml添加parse-pqdif.storage.path配置项 - 更新CsPqdifPath相关实体类将pqdifContent改为filePath存储路径 - 重构CsPqdifPathController中的文件上传处理逻辑 - 新增PqdifRecognizeResultVO支持PQDIF二次解析结果结构 - 实现ParsePqdifService接口支持可识别数据解析功能 - 添加PqdifSecondParseComponent进行底层解析结果转换 - 新增桌面PQDIF文件测试程序便于调试验证 - 为CsIcdPath增加referenceIcdId字段及相应测试用例
This commit is contained in:
@@ -62,6 +62,10 @@ log:
|
|||||||
homeDir: D:\logs
|
homeDir: D:\logs
|
||||||
commonLevel: info
|
commonLevel: info
|
||||||
|
|
||||||
|
parse-pqdif:
|
||||||
|
storage:
|
||||||
|
path: D:\pqdif-files
|
||||||
|
|
||||||
activate:
|
activate:
|
||||||
private-key: "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCcUyYhVqczGxblL+o/xZzF/8nf+LjrfUE/dS1aRHM7uMDD0cgCArhjtfneFePrMxt+Z7W8yNBzSarub8qsfhaVNikV7Es7oaeTygfjQXTi2n4AFkir3fM07J08RpWhl5M8f8uWTCuvFUYAw00gq55typqmnbkmJa2VIUy/iQf+cMCP7abz4/jNhUzUR3qA7TV4oMRgTdIEDUp63YF8dOC+JH8XxYrCVeHXV6fLCwmesdMzl0lB2VTEKMfLbXhOmF5g7P9y/16VCcN8UBuZlbyYfn+GAxJOSbeHi5HshOKfoSuD7Jz+3WQZpNavOWjIFExKIU38/CvnJCOP7XBCqpSTAgMBAAECggEAYeWokWRE3TpvwiOZnUpR/aVMdVi75a3ROL5XIpqPV61B+t/bU3cEpl0GF9C5pUeiRi0IoStZb3mI9D1KPW/REKyUWkhabQO1gFYbTnRlkNOn6MILzKX4cwJjDaZeeo4EBPU7N+qHyOOXrU6hdH5FfxhMdV983ajm5eeuupxER1C2kAcIklTeVpTX6EKOgZb5LBp5ssOVm2P42pOauvcRozRcvZmqnErXmukv0H4l3EVNt4rHpTn9riHUC63e8JfiYzVaF6zuNUxv6nHEft0/SRMw11XSTnNfDzcKqgjz6ksFBS/6eQQYKESk+ONC53HUuYHFAknkwsPupDCT2W8FIQKBgQDLHT/xCU3nxGr4vFKBDNaO2D5oK20ECbBO4oDvLWWmQG7f+6TsMy8PgVdMnoL4RfqGlwFAKEpS6KVFHnBVqnNEhcdy9uCI7x7Xx8UnyUtxj1EDTm76uta9Ki9OrlqB6tImDM9+Ya3vGktW37ht4WOx2OsJRhG1dbf6RLwFlH7DWwKBgQDFBxvi5I1BR6hg6Tj7xd2SqOT2Y+BED3xuSYENhWbmMhLJDResaB7mjztbxlYaY2mOE0holWm2uDmVFFhMh4jYXik4hYH8nmDzq9mDpZCZ9pyjYqnAP8THoAa8EbgrUWB8A6BPH4iL3KbMnBfBKY0pIr2xrvnjQjNBAgta7KDRKQKBgCe6oe4wxrdF2TKsC2tIqpMoQxS3Icy/ZGgZr+SYuaBKTCWtoDW/UT40K3JGMxIDBhzbXphBCUCsVt9tM8Xd4EwP6tJW7dZ7B0pnve2pVwNwaAVAiz6p2yUHIle+jN+Koe5lZRSwYIg7WW81tWpwwsJfzqFyvjYDP6hJV4mz4ROvAoGAaRcdnKvjXApomShMqJ4lTPChD3q+SA8qg3jZSOj6tZXHx00gb2kp8jg7pPvpOTIFPy6x1Ha9aCRjMk0ju84fA6lVuzwa1S907wOehUVuF3Eeo1cgy9Y3k3KbpPyeixxgpkUY4JslLdSHc2NemD0dee951qhJyRmqVOZOQDUuoeECgYEAqBw2cAFk3vM97WY06TSldGA8ajVHx3BYRjj+zl62NTQthy8fw3tqxb3c5e8toOmZWKjZvDhg2TRLhsDDQWEYg3LZG87REqVIjgEPcpjNLidjygGX8n3JF2o0O5I/EMvl0s/+LVQONfduOBvhwDqr8QNisbLsyneiAq7umewMolo="
|
private-key: "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCcUyYhVqczGxblL+o/xZzF/8nf+LjrfUE/dS1aRHM7uMDD0cgCArhjtfneFePrMxt+Z7W8yNBzSarub8qsfhaVNikV7Es7oaeTygfjQXTi2n4AFkir3fM07J08RpWhl5M8f8uWTCuvFUYAw00gq55typqmnbkmJa2VIUy/iQf+cMCP7abz4/jNhUzUR3qA7TV4oMRgTdIEDUp63YF8dOC+JH8XxYrCVeHXV6fLCwmesdMzl0lB2VTEKMfLbXhOmF5g7P9y/16VCcN8UBuZlbyYfn+GAxJOSbeHi5HshOKfoSuD7Jz+3WQZpNavOWjIFExKIU38/CvnJCOP7XBCqpSTAgMBAAECggEAYeWokWRE3TpvwiOZnUpR/aVMdVi75a3ROL5XIpqPV61B+t/bU3cEpl0GF9C5pUeiRi0IoStZb3mI9D1KPW/REKyUWkhabQO1gFYbTnRlkNOn6MILzKX4cwJjDaZeeo4EBPU7N+qHyOOXrU6hdH5FfxhMdV983ajm5eeuupxER1C2kAcIklTeVpTX6EKOgZb5LBp5ssOVm2P42pOauvcRozRcvZmqnErXmukv0H4l3EVNt4rHpTn9riHUC63e8JfiYzVaF6zuNUxv6nHEft0/SRMw11XSTnNfDzcKqgjz6ksFBS/6eQQYKESk+ONC53HUuYHFAknkwsPupDCT2W8FIQKBgQDLHT/xCU3nxGr4vFKBDNaO2D5oK20ECbBO4oDvLWWmQG7f+6TsMy8PgVdMnoL4RfqGlwFAKEpS6KVFHnBVqnNEhcdy9uCI7x7Xx8UnyUtxj1EDTm76uta9Ki9OrlqB6tImDM9+Ya3vGktW37ht4WOx2OsJRhG1dbf6RLwFlH7DWwKBgQDFBxvi5I1BR6hg6Tj7xd2SqOT2Y+BED3xuSYENhWbmMhLJDResaB7mjztbxlYaY2mOE0holWm2uDmVFFhMh4jYXik4hYH8nmDzq9mDpZCZ9pyjYqnAP8THoAa8EbgrUWB8A6BPH4iL3KbMnBfBKY0pIr2xrvnjQjNBAgta7KDRKQKBgCe6oe4wxrdF2TKsC2tIqpMoQxS3Icy/ZGgZr+SYuaBKTCWtoDW/UT40K3JGMxIDBhzbXphBCUCsVt9tM8Xd4EwP6tJW7dZ7B0pnve2pVwNwaAVAiz6p2yUHIle+jN+Koe5lZRSwYIg7WW81tWpwwsJfzqFyvjYDP6hJV4mz4ROvAoGAaRcdnKvjXApomShMqJ4lTPChD3q+SA8qg3jZSOj6tZXHx00gb2kp8jg7pPvpOTIFPy6x1Ha9aCRjMk0ju84fA6lVuzwa1S907wOehUVuF3Eeo1cgy9Y3k3KbpPyeixxgpkUY4JslLdSHc2NemD0dee951qhJyRmqVOZOQDUuoeECgYEAqBw2cAFk3vM97WY06TSldGA8ajVHx3BYRjj+zl62NTQthy8fw3tqxb3c5e8toOmZWKjZvDhg2TRLhsDDQWEYg3LZG87REqVIjgEPcpjNLidjygGX8n3JF2o0O5I/EMvl0s/+LVQONfduOBvhwDqr8QNisbLsyneiAq7umewMolo="
|
||||||
public-key: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnFMmIVanMxsW5S/qP8Wcxf/J3/i4631BP3UtWkRzO7jAw9HIAgK4Y7X53hXj6zMbfme1vMjQc0mq7m/KrH4WlTYpFexLO6Gnk8oH40F04tp+ABZIq93zNOydPEaVoZeTPH/LlkwrrxVGAMNNIKuebcqapp25JiWtlSFMv4kH/nDAj+2m8+P4zYVM1Ed6gO01eKDEYE3SBA1Ket2BfHTgviR/F8WKwlXh11enywsJnrHTM5dJQdlUxCjHy214TpheYOz/cv9elQnDfFAbmZW8mH5/hgMSTkm3h4uR7ITin6Erg+yc/t1kGaTWrzloyBRMSiFN/Pwr5yQjj+1wQqqUkwIDAQAB"
|
public-key: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnFMmIVanMxsW5S/qP8Wcxf/J3/i4631BP3UtWkRzO7jAw9HIAgK4Y7X53hXj6zMbfme1vMjQc0mq7m/KrH4WlTYpFexLO6Gnk8oH40F04tp+ABZIq93zNOydPEaVoZeTPH/LlkwrrxVGAMNNIKuebcqapp25JiWtlSFMv4kH/nDAj+2m8+P4zYVM1Ed6gO01eKDEYE3SBA1Ket2BfHTgviR/F8WKwlXh11enywsJnrHTM5dJQdlUxCjHy214TpheYOz/cv9elQnDfFAbmZW8mH5/hgMSTkm3h4uR7ITin6Erg+yc/t1kGaTWrzloyBRMSiFN/Pwr5yQjj+1wQqqUkwIDAQAB"
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ public class CsIcdPathParam {
|
|||||||
@ApiModelProperty("ICD类型,1-手动录入的标准ICD,2-手动录入的非标准ICD,3-上游解析传递的标准ICD,4-上游解析传递的非标准ICD")
|
@ApiModelProperty("ICD类型,1-手动录入的标准ICD,2-手动录入的非标准ICD,3-上游解析传递的标准ICD,4-上游解析传递的非标准ICD")
|
||||||
private Integer type;
|
private Integer type;
|
||||||
|
|
||||||
|
@ApiModelProperty("标准ICD引用ID")
|
||||||
|
private String referenceIcdId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ICD 存储记录编辑参数。
|
* ICD 存储记录编辑参数。
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -189,6 +189,7 @@ public class CsIcdPathServiceImpl implements CsIcdPathService {
|
|||||||
icdPath.setAngle(param.getAngle());
|
icdPath.setAngle(param.getAngle());
|
||||||
icdPath.setUsePhaseIndex(param.getUsePhaseIndex());
|
icdPath.setUsePhaseIndex(param.getUsePhaseIndex());
|
||||||
icdPath.setType(useDefaultType ? resolveIcdType(param.getType()) : param.getType());
|
icdPath.setType(useDefaultType ? resolveIcdType(param.getType()) : param.getType());
|
||||||
|
icdPath.setReferenceIcdId(trimToNull(param.getReferenceIcdId()));
|
||||||
return icdPath;
|
return icdPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -100,6 +100,20 @@ class CsIcdPathServiceImplTest {
|
|||||||
Assertions.assertArrayEquals(fileContent, captor.getValue().getIcdContent());
|
Assertions.assertArrayEquals(fileContent, captor.getValue().getIcdContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void addIcdPathShouldSaveReferenceIcdId() {
|
||||||
|
CsIcdPathParam param = buildParam("非标准ICD");
|
||||||
|
param.setReferenceIcdId(" reference-icd ");
|
||||||
|
when(csIcdPathMapper.insert(any(CsIcdPathPO.class))).thenReturn(1);
|
||||||
|
|
||||||
|
boolean result = service.addIcdPath(param);
|
||||||
|
|
||||||
|
ArgumentCaptor<CsIcdPathPO> captor = ArgumentCaptor.forClass(CsIcdPathPO.class);
|
||||||
|
verify(csIcdPathMapper).insert(captor.capture());
|
||||||
|
Assertions.assertTrue(result);
|
||||||
|
Assertions.assertEquals("reference-icd", captor.getValue().getReferenceIcdId());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void addIcdPathShouldDefaultTypeToManualNonStandard() {
|
void addIcdPathShouldDefaultTypeToManualNonStandard() {
|
||||||
CsIcdPathParam param = buildParam("手动录入非标准ICD");
|
CsIcdPathParam param = buildParam("手动录入非标准ICD");
|
||||||
|
|||||||
@@ -55,6 +55,12 @@
|
|||||||
<scope>system</scope>
|
<scope>system</scope>
|
||||||
<systemPath>${project.basedir}/lib/pqdif-native-basic-bridge-1.0.0-jar-with-dependencies.jar</systemPath>
|
<systemPath>${project.basedir}/lib/pqdif-native-basic-bridge-1.0.0-jar-with-dependencies.jar</systemPath>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package com.njcn.gather.tool.parsepqdif.component;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PQDIF 原始文件本地存储服务。
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class PqdifFileStorageService {
|
||||||
|
|
||||||
|
private static final String DEFAULT_STORAGE_DIR = "data/parse-pqdif";
|
||||||
|
|
||||||
|
@Value("${parse-pqdif.storage.path:}")
|
||||||
|
private String storagePath;
|
||||||
|
|
||||||
|
public String save(MultipartFile pqdifFile) {
|
||||||
|
if (pqdifFile == null || pqdifFile.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("PQDIF文件不能为空");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Path storageDir = resolveStorageDir();
|
||||||
|
Files.createDirectories(storageDir);
|
||||||
|
if (!Files.isDirectory(storageDir)) {
|
||||||
|
throw new IllegalStateException("PQDIF文件存储路径不是目录:" + storageDir);
|
||||||
|
}
|
||||||
|
String fileName = UUID.randomUUID().toString().replace("-", "") + "_" + sanitizeFileName(pqdifFile.getOriginalFilename());
|
||||||
|
Path target = storageDir.resolve(fileName).normalize();
|
||||||
|
if (!target.startsWith(storageDir)) {
|
||||||
|
throw new IllegalArgumentException("PQDIF文件名不合法");
|
||||||
|
}
|
||||||
|
try (InputStream inputStream = pqdifFile.getInputStream()) {
|
||||||
|
Files.copy(inputStream, target, StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
}
|
||||||
|
return target.toString();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new IllegalArgumentException("保存PQDIF文件失败:" + ex.getMessage(), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Path resolveStorageDir() {
|
||||||
|
String configuredPath = trimToNull(storagePath);
|
||||||
|
Path path = configuredPath == null ? Paths.get(DEFAULT_STORAGE_DIR) : Paths.get(configuredPath);
|
||||||
|
return path.toAbsolutePath().normalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String sanitizeFileName(String originalFilename) {
|
||||||
|
String fileName = trimToNull(originalFilename);
|
||||||
|
if (fileName == null) {
|
||||||
|
return "unnamed.pqd";
|
||||||
|
}
|
||||||
|
String normalizedName = Paths.get(fileName).getFileName().toString();
|
||||||
|
return normalizedName.replaceAll("[\\\\/:*?\"<>|]", "_");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String trimToNull(String value) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String text = value.trim();
|
||||||
|
return text.isEmpty() ? null : text;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,281 @@
|
|||||||
|
package com.njcn.gather.tool.parsepqdif.component;
|
||||||
|
|
||||||
|
import com.njcn.gather.tool.parsepqdif.pojo.vo.PqdifParseResponse;
|
||||||
|
import com.njcn.gather.tool.parsepqdif.pojo.vo.PqdifRecognizeResultVO;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.format.DateTimeParseException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 parse 方法返回的底层 PQDIF 解析结果转换为业务可识别结构。
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class PqdifSecondParseComponent {
|
||||||
|
|
||||||
|
private static final String STATUS_SUCCESS = "SUCCESS";
|
||||||
|
private static final String STATUS_FAILED = "FAILED";
|
||||||
|
private static final String MESSAGE_SUCCESS = "PQDIF二次解析完成";
|
||||||
|
|
||||||
|
private static final DateTimeFormatter STANDARD_DATE_TIME_FORMATTER =
|
||||||
|
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
private static final Map<Long, PhaseInfo> PHASE_MAP = buildPhaseMap();
|
||||||
|
private static final Map<Long, String> MEASUREMENT_MAP = buildMeasurementMap();
|
||||||
|
private static final Map<Long, String> UNIT_MAP = buildUnitMap();
|
||||||
|
private static final Map<Long, String> SERIES_BASE_TYPE_MAP = buildSeriesBaseTypeMap();
|
||||||
|
|
||||||
|
public PqdifRecognizeResultVO parseRecognizableData(PqdifParseResponse parseResponse) {
|
||||||
|
if (parseResponse == null) {
|
||||||
|
return failed("parse解析结果不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!STATUS_SUCCESS.equals(parseResponse.getStatus())) {
|
||||||
|
String message = parseResponse.getMessage() == null ? "" : parseResponse.getMessage();
|
||||||
|
return failed("parse解析未成功,不能进行二次解析:" + message);
|
||||||
|
}
|
||||||
|
|
||||||
|
PqdifRecognizeResultVO result = emptyResult(STATUS_SUCCESS, MESSAGE_SUCCESS);
|
||||||
|
List<PqdifParseResponse.ObservationVO> sourceObservations = parseResponse.getObservations();
|
||||||
|
if (sourceObservations == null || sourceObservations.isEmpty()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int observationIndex = 0; observationIndex < sourceObservations.size(); observationIndex++) {
|
||||||
|
PqdifParseResponse.ObservationVO sourceObservation = sourceObservations.get(observationIndex);
|
||||||
|
result.getObservations().add(parseObservation(sourceObservation, observationIndex, result));
|
||||||
|
}
|
||||||
|
|
||||||
|
result.setObservationCount((long) result.getObservations().size());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PqdifRecognizeResultVO.RecognizedObservationVO parseObservation(
|
||||||
|
PqdifParseResponse.ObservationVO source,
|
||||||
|
int observationIndex,
|
||||||
|
PqdifRecognizeResultVO result) {
|
||||||
|
|
||||||
|
PqdifRecognizeResultVO.RecognizedObservationVO target = new PqdifRecognizeResultVO.RecognizedObservationVO();
|
||||||
|
target.setRecordIndex(source == null ? null : source.getRecordIndex());
|
||||||
|
target.setName(source == null ? null : source.getName());
|
||||||
|
target.setStartTime(source == null ? null : formatStartTime(source.getTimeStartText()));
|
||||||
|
target.setChannels(new ArrayList<PqdifRecognizeResultVO.RecognizedChannelVO>());
|
||||||
|
|
||||||
|
if (source == null || source.getChannels() == null || source.getChannels().isEmpty()) {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int channelIndex = 0; channelIndex < source.getChannels().size(); channelIndex++) {
|
||||||
|
PqdifParseResponse.ChannelInfoVO sourceChannel = source.getChannels().get(channelIndex);
|
||||||
|
target.getChannels().add(parseChannel(sourceChannel, observationIndex, channelIndex, result));
|
||||||
|
result.setChannelCount(result.getChannelCount() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PqdifRecognizeResultVO.RecognizedChannelVO parseChannel(
|
||||||
|
PqdifParseResponse.ChannelInfoVO source,
|
||||||
|
int observationIndex,
|
||||||
|
int channelIndex,
|
||||||
|
PqdifRecognizeResultVO result) {
|
||||||
|
|
||||||
|
PqdifRecognizeResultVO.RecognizedChannelVO target = new PqdifRecognizeResultVO.RecognizedChannelVO();
|
||||||
|
target.setChannelIndex(source == null ? null : source.getChannelIndex());
|
||||||
|
target.setName(source == null ? null : source.getName());
|
||||||
|
target.setPhaseId(source == null ? null : source.getPhaseId());
|
||||||
|
target.setQuantityMeasuredId(source == null ? null : source.getQuantityMeasuredId());
|
||||||
|
target.setQuantityTypeGuid(source == null ? null : source.getQuantityTypeGuid());
|
||||||
|
target.setSeries(new ArrayList<PqdifRecognizeResultVO.RecognizedSeriesVO>());
|
||||||
|
|
||||||
|
if (source == null) {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
PhaseInfo phaseInfo = PHASE_MAP.get(source.getPhaseId());
|
||||||
|
if (phaseInfo == null) {
|
||||||
|
addUnknown(result, channelPath(observationIndex, channelIndex), "phaseId", source.getPhaseId(), "未识别的相别ID");
|
||||||
|
} else {
|
||||||
|
target.setPhaseCode(phaseInfo.getCode());
|
||||||
|
target.setPhaseName(phaseInfo.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
String measurementName = MEASUREMENT_MAP.get(source.getQuantityMeasuredId());
|
||||||
|
if (measurementName == null) {
|
||||||
|
addUnknown(result, channelPath(observationIndex, channelIndex),
|
||||||
|
"quantityMeasuredId", source.getQuantityMeasuredId(), "未识别的测量量ID");
|
||||||
|
} else {
|
||||||
|
target.setMeasurementName(measurementName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source.getSeries() == null || source.getSeries().isEmpty()) {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int seriesIndex = 0; seriesIndex < source.getSeries().size(); seriesIndex++) {
|
||||||
|
PqdifParseResponse.SeriesInfoVO sourceSeries = source.getSeries().get(seriesIndex);
|
||||||
|
target.getSeries().add(parseSeries(sourceSeries, observationIndex, channelIndex, seriesIndex, result));
|
||||||
|
result.setSeriesCount(result.getSeriesCount() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PqdifRecognizeResultVO.RecognizedSeriesVO parseSeries(
|
||||||
|
PqdifParseResponse.SeriesInfoVO source,
|
||||||
|
int observationIndex,
|
||||||
|
int channelIndex,
|
||||||
|
int seriesIndex,
|
||||||
|
PqdifRecognizeResultVO result) {
|
||||||
|
|
||||||
|
PqdifRecognizeResultVO.RecognizedSeriesVO target = new PqdifRecognizeResultVO.RecognizedSeriesVO();
|
||||||
|
if (source == null) {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
target.setSeriesIndex(source.getSeriesIndex());
|
||||||
|
target.setQuantityUnitsId(source.getQuantityUnitsId());
|
||||||
|
target.setQuantityCharacteristicGuid(source.getQuantityCharacteristicGuid());
|
||||||
|
target.setValueTypeGuid(source.getValueTypeGuid());
|
||||||
|
target.setSeriesBaseType(source.getSeriesBaseType());
|
||||||
|
target.setScale(source.getScale());
|
||||||
|
target.setOffset(source.getOffset());
|
||||||
|
target.setDataStatus(source.getDataStatus());
|
||||||
|
target.setDataMessage(source.getDataMessage());
|
||||||
|
target.setValueCount(source.getValueCount());
|
||||||
|
target.setFirstValues(source.getFirstValues());
|
||||||
|
|
||||||
|
String unitName = UNIT_MAP.get(source.getQuantityUnitsId());
|
||||||
|
if (unitName == null) {
|
||||||
|
addUnknown(result, seriesPath(observationIndex, channelIndex, seriesIndex),
|
||||||
|
"quantityUnitsId", source.getQuantityUnitsId(), "未识别的单位ID");
|
||||||
|
} else {
|
||||||
|
target.setUnitName(unitName);
|
||||||
|
}
|
||||||
|
|
||||||
|
String dataTypeName = SERIES_BASE_TYPE_MAP.get(source.getSeriesBaseType());
|
||||||
|
if (dataTypeName == null) {
|
||||||
|
addUnknown(result, seriesPath(observationIndex, channelIndex, seriesIndex),
|
||||||
|
"seriesBaseType", source.getSeriesBaseType(), "未识别的Series基础类型");
|
||||||
|
} else {
|
||||||
|
target.setDataTypeName(dataTypeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PqdifRecognizeResultVO failed(String message) {
|
||||||
|
return emptyResult(STATUS_FAILED, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatStartTime(String timeStartText) {
|
||||||
|
if (timeStartText == null || timeStartText.trim().isEmpty()) {
|
||||||
|
return timeStartText;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return LocalDateTime.parse(timeStartText.trim()).format(STANDARD_DATE_TIME_FORMATTER);
|
||||||
|
} catch (DateTimeParseException e) {
|
||||||
|
return timeStartText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PqdifRecognizeResultVO emptyResult(String status, String message) {
|
||||||
|
PqdifRecognizeResultVO result = new PqdifRecognizeResultVO();
|
||||||
|
result.setStatus(status);
|
||||||
|
result.setMessage(message);
|
||||||
|
result.setObservationCount(0L);
|
||||||
|
result.setChannelCount(0L);
|
||||||
|
result.setSeriesCount(0L);
|
||||||
|
result.setObservations(new ArrayList<PqdifRecognizeResultVO.RecognizedObservationVO>());
|
||||||
|
result.setUnknownItems(new ArrayList<PqdifRecognizeResultVO.UnknownItemVO>());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addUnknown(PqdifRecognizeResultVO result, String path, String fieldName, Object fieldValue, String message) {
|
||||||
|
if (fieldValue == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PqdifRecognizeResultVO.UnknownItemVO item = new PqdifRecognizeResultVO.UnknownItemVO();
|
||||||
|
item.setPath(path);
|
||||||
|
item.setFieldName(fieldName);
|
||||||
|
item.setFieldValue(String.valueOf(fieldValue));
|
||||||
|
item.setMessage(message);
|
||||||
|
result.getUnknownItems().add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String channelPath(int observationIndex, int channelIndex) {
|
||||||
|
return "observations[" + observationIndex + "].channels[" + channelIndex + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String seriesPath(int observationIndex, int channelIndex, int seriesIndex) {
|
||||||
|
return channelPath(observationIndex, channelIndex) + ".series[" + seriesIndex + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<Long, PhaseInfo> buildPhaseMap() {
|
||||||
|
Map<Long, PhaseInfo> map = new HashMap<Long, PhaseInfo>();
|
||||||
|
map.put(0L, new PhaseInfo("UNKNOWN", "未知相别"));
|
||||||
|
map.put(1L, new PhaseInfo("A", "A相"));
|
||||||
|
map.put(2L, new PhaseInfo("B", "B相"));
|
||||||
|
map.put(3L, new PhaseInfo("C", "C相"));
|
||||||
|
map.put(4L, new PhaseInfo("N", "中性线"));
|
||||||
|
map.put(5L, new PhaseInfo("AB", "AB线电压"));
|
||||||
|
map.put(6L, new PhaseInfo("BC", "BC线电压"));
|
||||||
|
map.put(7L, new PhaseInfo("CA", "CA线电压"));
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<Long, String> buildMeasurementMap() {
|
||||||
|
Map<Long, String> map = new HashMap<Long, String>();
|
||||||
|
map.put(0L, "电压");
|
||||||
|
map.put(1L, "电流");
|
||||||
|
map.put(2L, "频率");
|
||||||
|
map.put(3L, "有功功率");
|
||||||
|
map.put(4L, "无功功率");
|
||||||
|
map.put(5L, "视在功率");
|
||||||
|
map.put(6L, "功率因数");
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<Long, String> buildUnitMap() {
|
||||||
|
Map<Long, String> map = new HashMap<Long, String>();
|
||||||
|
map.put(27L, "A");
|
||||||
|
map.put(29L, "V");
|
||||||
|
map.put(32L, "Hz");
|
||||||
|
map.put(38L, "W");
|
||||||
|
map.put(39L, "var");
|
||||||
|
map.put(40L, "VA");
|
||||||
|
map.put(41L, "%");
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<Long, String> buildSeriesBaseTypeMap() {
|
||||||
|
Map<Long, String> map = new HashMap<Long, String>();
|
||||||
|
map.put(1L, "DOUBLE");
|
||||||
|
map.put(2L, "INTEGER");
|
||||||
|
map.put(3L, "BOOLEAN");
|
||||||
|
map.put(4L, "TEXT");
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class PhaseInfo {
|
||||||
|
private final String code;
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
private PhaseInfo(String code, String name) {
|
||||||
|
this.code = code;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import com.njcn.common.pojo.enums.common.LogEnum;
|
|||||||
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
|
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
|
||||||
import com.njcn.common.pojo.response.HttpResult;
|
import com.njcn.common.pojo.response.HttpResult;
|
||||||
import com.njcn.common.utils.LogUtil;
|
import com.njcn.common.utils.LogUtil;
|
||||||
|
import com.njcn.gather.tool.parsepqdif.component.PqdifFileStorageService;
|
||||||
import com.njcn.gather.tool.parsepqdif.pojo.param.CsPqdifPathParam;
|
import com.njcn.gather.tool.parsepqdif.pojo.param.CsPqdifPathParam;
|
||||||
import com.njcn.gather.tool.parsepqdif.pojo.param.PqdifParseResultSaveParam;
|
import com.njcn.gather.tool.parsepqdif.pojo.param.PqdifParseResultSaveParam;
|
||||||
import com.njcn.gather.tool.parsepqdif.pojo.vo.CsPqdifPathDetailVO;
|
import com.njcn.gather.tool.parsepqdif.pojo.vo.CsPqdifPathDetailVO;
|
||||||
@@ -27,7 +28,6 @@ import org.springframework.web.bind.annotation.RequestPart;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,6 +42,8 @@ public class CsPqdifPathController extends BaseController {
|
|||||||
|
|
||||||
private final CsPqdifPathService csPqdifPathService;
|
private final CsPqdifPathService csPqdifPathService;
|
||||||
|
|
||||||
|
private final PqdifFileStorageService pqdifFileStorageService;
|
||||||
|
|
||||||
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
|
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
|
||||||
@ApiOperation("查询PQDIF存储记录列表")
|
@ApiOperation("查询PQDIF存储记录列表")
|
||||||
@PostMapping("/list")
|
@PostMapping("/list")
|
||||||
@@ -69,7 +71,7 @@ public class CsPqdifPathController extends BaseController {
|
|||||||
@RequestPart("request") @Validated CsPqdifPathParam param) {
|
@RequestPart("request") @Validated CsPqdifPathParam param) {
|
||||||
String methodDescribe = getMethodDescribe("addWithFile");
|
String methodDescribe = getMethodDescribe("addWithFile");
|
||||||
LogUtil.njcnDebug(log, "{},开始上传并新增PQDIF存储记录,fileName={}", methodDescribe, resolveFileName(pqdifFile));
|
LogUtil.njcnDebug(log, "{},开始上传并新增PQDIF存储记录,fileName={}", methodDescribe, resolveFileName(pqdifFile));
|
||||||
fillPqdifFile(param, pqdifFile);
|
fillPqdifFilePath(param, pqdifFile);
|
||||||
boolean result = csPqdifPathService.addPqdifPath(param);
|
boolean result = csPqdifPathService.addPqdifPath(param);
|
||||||
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
|
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
|
||||||
}
|
}
|
||||||
@@ -92,7 +94,7 @@ public class CsPqdifPathController extends BaseController {
|
|||||||
String methodDescribe = getMethodDescribe("updateWithFile");
|
String methodDescribe = getMethodDescribe("updateWithFile");
|
||||||
LogUtil.njcnDebug(log, "{},开始上传并编辑PQDIF存储记录,pqdifId={},fileName={}",
|
LogUtil.njcnDebug(log, "{},开始上传并编辑PQDIF存储记录,pqdifId={},fileName={}",
|
||||||
methodDescribe, param.getId(), resolveFileName(pqdifFile));
|
methodDescribe, param.getId(), resolveFileName(pqdifFile));
|
||||||
fillPqdifFile(param, pqdifFile);
|
fillPqdifFilePath(param, pqdifFile);
|
||||||
boolean result = csPqdifPathService.updatePqdifPath(param);
|
boolean result = csPqdifPathService.updatePqdifPath(param);
|
||||||
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
|
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
|
||||||
}
|
}
|
||||||
@@ -141,15 +143,8 @@ public class CsPqdifPathController extends BaseController {
|
|||||||
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
|
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillPqdifFile(CsPqdifPathParam param, MultipartFile pqdifFile) {
|
private void fillPqdifFilePath(CsPqdifPathParam param, MultipartFile pqdifFile) {
|
||||||
if (pqdifFile == null || pqdifFile.isEmpty()) {
|
param.setFilePath(pqdifFileStorageService.save(pqdifFile));
|
||||||
throw new IllegalArgumentException("PQDIF文件不能为空");
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
param.setPqdifContent(pqdifFile.getBytes());
|
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new IllegalArgumentException("读取PQDIF文件失败:" + ex.getMessage(), ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String resolveFileName(MultipartFile pqdifFile) {
|
private String resolveFileName(MultipartFile pqdifFile) {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import com.njcn.common.pojo.enums.response.CommonResponseEnum;
|
|||||||
import com.njcn.common.pojo.response.HttpResult;
|
import com.njcn.common.pojo.response.HttpResult;
|
||||||
import com.njcn.common.utils.LogUtil;
|
import com.njcn.common.utils.LogUtil;
|
||||||
import com.njcn.gather.tool.parsepqdif.pojo.vo.PqdifParseResponse;
|
import com.njcn.gather.tool.parsepqdif.pojo.vo.PqdifParseResponse;
|
||||||
|
import com.njcn.gather.tool.parsepqdif.pojo.vo.PqdifRecognizeResultVO;
|
||||||
import com.njcn.gather.tool.parsepqdif.service.ParsePqdifService;
|
import com.njcn.gather.tool.parsepqdif.service.ParsePqdifService;
|
||||||
import com.njcn.web.controller.BaseController;
|
import com.njcn.web.controller.BaseController;
|
||||||
import com.njcn.web.utils.HttpResultUtil;
|
import com.njcn.web.utils.HttpResultUtil;
|
||||||
@@ -43,4 +44,17 @@ public class ParsePqdifController extends BaseController {
|
|||||||
PqdifParseResponse result = parsePqdifService.parse(pqdifFile);
|
PqdifParseResponse result = parsePqdifService.parse(pqdifFile);
|
||||||
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
|
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
|
||||||
|
@ApiOperation("上传 PQDIF 文件并解析为可识别数据")
|
||||||
|
@ApiImplicitParam(name = "pqdifFile", value = "PQDIF文件", required = true, dataType = "__file", paramType = "form")
|
||||||
|
@PostMapping(value = "/parse-recognizable", consumes = {"multipart/form-data"})
|
||||||
|
public HttpResult<PqdifRecognizeResultVO> parseRecognizable(@RequestPart("pqdifFile") MultipartFile pqdifFile) {
|
||||||
|
String methodDescribe = getMethodDescribe("parseRecognizable");
|
||||||
|
LogUtil.njcnDebug(log, "{},PQDIF二次解析入口,fileName={}",
|
||||||
|
methodDescribe, pqdifFile == null ? null : pqdifFile.getOriginalFilename());
|
||||||
|
PqdifParseResponse parseResponse = parsePqdifService.parse(pqdifFile);
|
||||||
|
PqdifRecognizeResultVO result = parsePqdifService.parseRecognizable(parseResponse);
|
||||||
|
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
type="com.njcn.gather.tool.parsepqdif.pojo.vo.CsPqdifPathVO">
|
type="com.njcn.gather.tool.parsepqdif.pojo.vo.CsPqdifPathVO">
|
||||||
<id column="id" property="id"/>
|
<id column="id" property="id"/>
|
||||||
<result column="name" property="name"/>
|
<result column="name" property="name"/>
|
||||||
<result column="nativeVersion" property="nativeVersion"/>
|
<result column="filePath" property="filePath"/>
|
||||||
<result column="recordCount" property="recordCount"/>
|
<result column="recordCount" property="recordCount"/>
|
||||||
<result column="observationCount" property="observationCount"/>
|
<result column="observationCount" property="observationCount"/>
|
||||||
<result column="sampleValueCount" property="sampleValueCount"/>
|
<result column="sampleValueCount" property="sampleValueCount"/>
|
||||||
@@ -26,13 +26,12 @@
|
|||||||
SELECT
|
SELECT
|
||||||
ID AS id,
|
ID AS id,
|
||||||
Name AS name,
|
Name AS name,
|
||||||
Native_Version AS nativeVersion,
|
File_Path AS filePath,
|
||||||
Record_Count AS recordCount,
|
Record_Count AS recordCount,
|
||||||
Observation_Count AS observationCount,
|
Observation_Count AS observationCount,
|
||||||
Sample_Value_Count AS sampleValueCount,
|
Sample_Value_Count AS sampleValueCount,
|
||||||
State AS state,
|
State AS state,
|
||||||
Result AS result,
|
Result AS result,
|
||||||
Msg AS msg,
|
|
||||||
Create_By AS createBy,
|
Create_By AS createBy,
|
||||||
Create_Time AS createTime,
|
Create_Time AS createTime,
|
||||||
Update_By AS updateBy,
|
Update_By AS updateBy,
|
||||||
@@ -61,8 +60,7 @@
|
|||||||
SELECT
|
SELECT
|
||||||
ID AS id,
|
ID AS id,
|
||||||
Name AS name,
|
Name AS name,
|
||||||
Json_Str AS jsonStr,
|
File_Path AS filePath
|
||||||
Pqdif AS pqdifContent
|
|
||||||
FROM cs_pqdif_path
|
FROM cs_pqdif_path
|
||||||
WHERE ID = #{id}
|
WHERE ID = #{id}
|
||||||
AND State = 1
|
AND State = 1
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.njcn.gather.tool.parsepqdif.pojo.param;
|
package com.njcn.gather.tool.parsepqdif.pojo.param;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -18,8 +19,9 @@ public class CsPqdifPathParam {
|
|||||||
@NotBlank(message = "PQDIF名称不能为空")
|
@NotBlank(message = "PQDIF名称不能为空")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@ApiModelProperty("PQDIF文件二进制内容")
|
@ApiModelProperty("PQDIF原始文件存储路径")
|
||||||
private byte[] pqdifContent;
|
@JsonIgnore
|
||||||
|
private String filePath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PQDIF 存储记录编辑参数。
|
* PQDIF 存储记录编辑参数。
|
||||||
|
|||||||
@@ -12,9 +12,6 @@ import lombok.Data;
|
|||||||
@ApiModel("PQDIF解析结果保存参数")
|
@ApiModel("PQDIF解析结果保存参数")
|
||||||
public class PqdifParseResultSaveParam {
|
public class PqdifParseResultSaveParam {
|
||||||
|
|
||||||
@ApiModelProperty("native解析库版本")
|
|
||||||
private String nativeVersion;
|
|
||||||
|
|
||||||
@ApiModelProperty("Record总数")
|
@ApiModelProperty("Record总数")
|
||||||
private Long recordCount;
|
private Long recordCount;
|
||||||
|
|
||||||
@@ -30,6 +27,4 @@ public class PqdifParseResultSaveParam {
|
|||||||
@ApiModelProperty("解析提示、失败原因或解析结论JSON")
|
@ApiModelProperty("解析提示、失败原因或解析结论JSON")
|
||||||
private JsonNode msg;
|
private JsonNode msg;
|
||||||
|
|
||||||
@ApiModelProperty("完整PQDIF解析结果JSON")
|
|
||||||
private String jsonStr;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,11 +25,8 @@ public class CsPqdifPathPO implements Serializable {
|
|||||||
@TableField("Name")
|
@TableField("Name")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@TableField("Pqdif")
|
@TableField("File_Path")
|
||||||
private byte[] pqdifContent;
|
private String filePath;
|
||||||
|
|
||||||
@TableField("Native_Version")
|
|
||||||
private String nativeVersion;
|
|
||||||
|
|
||||||
@TableField("Record_Count")
|
@TableField("Record_Count")
|
||||||
private Long recordCount;
|
private Long recordCount;
|
||||||
@@ -46,9 +43,6 @@ public class CsPqdifPathPO implements Serializable {
|
|||||||
@TableField(value = "Msg", typeHandler = JsonNodeTypeHandler.class)
|
@TableField(value = "Msg", typeHandler = JsonNodeTypeHandler.class)
|
||||||
private JsonNode msg;
|
private JsonNode msg;
|
||||||
|
|
||||||
@TableField("Json_Str")
|
|
||||||
private String jsonStr;
|
|
||||||
|
|
||||||
@TableField("State")
|
@TableField("State")
|
||||||
private Integer state;
|
private Integer state;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.njcn.gather.tool.parsepqdif.pojo.vo;
|
package com.njcn.gather.tool.parsepqdif.pojo.vo;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -18,9 +17,6 @@ public class CsPqdifPathDetailVO {
|
|||||||
@ApiModelProperty("PQDIF名称")
|
@ApiModelProperty("PQDIF名称")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@ApiModelProperty("完整PQDIF解析结果JSON")
|
@ApiModelProperty("PQDIF原始文件存储路径")
|
||||||
private String jsonStr;
|
private String filePath;
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
private byte[] pqdifContent;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ public class CsPqdifPathVO {
|
|||||||
@ApiModelProperty("PQDIF名称")
|
@ApiModelProperty("PQDIF名称")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@ApiModelProperty("native解析库版本")
|
@ApiModelProperty("PQDIF原始文件存储路径")
|
||||||
private String nativeVersion;
|
private String filePath;
|
||||||
|
|
||||||
@ApiModelProperty("Record总数")
|
@ApiModelProperty("Record总数")
|
||||||
private Long recordCount;
|
private Long recordCount;
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package com.njcn.gather.tool.parsepqdif.pojo.vo;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@ApiModel("PQDIF二次解析结果")
|
||||||
|
public class PqdifRecognizeResultVO {
|
||||||
|
|
||||||
|
@ApiModelProperty("状态:SUCCESS / FAILED")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
@ApiModelProperty("提示信息")
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
@ApiModelProperty("Observation数量")
|
||||||
|
private Long observationCount;
|
||||||
|
|
||||||
|
@ApiModelProperty("Channel数量")
|
||||||
|
private Long channelCount;
|
||||||
|
|
||||||
|
@ApiModelProperty("Series数量")
|
||||||
|
private Long seriesCount;
|
||||||
|
|
||||||
|
@ApiModelProperty("可识别Observation列表")
|
||||||
|
private List<RecognizedObservationVO> observations;
|
||||||
|
|
||||||
|
@ApiModelProperty("未识别字段列表")
|
||||||
|
private List<UnknownItemVO> unknownItems;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class RecognizedObservationVO {
|
||||||
|
private Long recordIndex;
|
||||||
|
private String name;
|
||||||
|
private String startTime;
|
||||||
|
private List<RecognizedChannelVO> channels;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class RecognizedChannelVO {
|
||||||
|
private Long channelIndex;
|
||||||
|
private String name;
|
||||||
|
private String phaseCode;
|
||||||
|
private String phaseName;
|
||||||
|
private String measurementName;
|
||||||
|
private Long phaseId;
|
||||||
|
private Long quantityMeasuredId;
|
||||||
|
private String quantityTypeGuid;
|
||||||
|
private List<RecognizedSeriesVO> series;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class RecognizedSeriesVO {
|
||||||
|
private Long seriesIndex;
|
||||||
|
private String unitName;
|
||||||
|
private String characteristicName;
|
||||||
|
private String valueTypeName;
|
||||||
|
private String dataTypeName;
|
||||||
|
private Long quantityUnitsId;
|
||||||
|
private String quantityCharacteristicGuid;
|
||||||
|
private String valueTypeGuid;
|
||||||
|
private Long seriesBaseType;
|
||||||
|
private Double scale;
|
||||||
|
private Double offset;
|
||||||
|
private String dataStatus;
|
||||||
|
private String dataMessage;
|
||||||
|
private Integer valueCount;
|
||||||
|
private List<Double> firstValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class UnknownItemVO {
|
||||||
|
private String path;
|
||||||
|
private String fieldName;
|
||||||
|
private String fieldValue;
|
||||||
|
private String message;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.njcn.gather.tool.parsepqdif.service;
|
package com.njcn.gather.tool.parsepqdif.service;
|
||||||
|
|
||||||
import com.njcn.gather.tool.parsepqdif.pojo.vo.PqdifParseResponse;
|
import com.njcn.gather.tool.parsepqdif.pojo.vo.PqdifParseResponse;
|
||||||
|
import com.njcn.gather.tool.parsepqdif.pojo.vo.PqdifRecognizeResultVO;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -9,4 +10,6 @@ import org.springframework.web.multipart.MultipartFile;
|
|||||||
public interface ParsePqdifService {
|
public interface ParsePqdifService {
|
||||||
|
|
||||||
PqdifParseResponse parse(MultipartFile pqdifFile);
|
PqdifParseResponse parse(MultipartFile pqdifFile);
|
||||||
|
|
||||||
|
PqdifRecognizeResultVO parseRecognizable(PqdifParseResponse parseResponse);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package com.njcn.gather.tool.parsepqdif.service.impl;
|
package com.njcn.gather.tool.parsepqdif.service.impl;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import com.njcn.gather.tool.parsepqdif.mapper.CsPqdifPathMapper;
|
import com.njcn.gather.tool.parsepqdif.mapper.CsPqdifPathMapper;
|
||||||
import com.njcn.gather.tool.parsepqdif.pojo.param.CsPqdifPathParam;
|
import com.njcn.gather.tool.parsepqdif.pojo.param.CsPqdifPathParam;
|
||||||
import com.njcn.gather.tool.parsepqdif.pojo.param.PqdifParseResultSaveParam;
|
import com.njcn.gather.tool.parsepqdif.pojo.param.PqdifParseResultSaveParam;
|
||||||
@@ -29,6 +31,8 @@ public class CsPqdifPathServiceImpl implements CsPqdifPathService {
|
|||||||
|
|
||||||
private static final int STATE_DELETED = 0;
|
private static final int STATE_DELETED = 0;
|
||||||
|
|
||||||
|
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||||
|
|
||||||
private final CsPqdifPathMapper csPqdifPathMapper;
|
private final CsPqdifPathMapper csPqdifPathMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -71,7 +75,7 @@ public class CsPqdifPathServiceImpl implements CsPqdifPathService {
|
|||||||
@Transactional
|
@Transactional
|
||||||
public boolean updatePqdifPath(CsPqdifPathParam.UpdateParam param) {
|
public boolean updatePqdifPath(CsPqdifPathParam.UpdateParam param) {
|
||||||
CsPqdifPathParam.UpdateParam checkedParam = requireUpdateParam(param);
|
CsPqdifPathParam.UpdateParam checkedParam = requireUpdateParam(param);
|
||||||
requirePqdifPath(checkedParam.getId());
|
requireNormalPqdifPath(checkedParam.getId());
|
||||||
CsPqdifPathPO pqdifPath = buildPqdifPath(checkedParam);
|
CsPqdifPathPO pqdifPath = buildPqdifPath(checkedParam);
|
||||||
pqdifPath.setId(checkedParam.getId());
|
pqdifPath.setId(checkedParam.getId());
|
||||||
pqdifPath.setUpdateBy(currentUserId());
|
pqdifPath.setUpdateBy(currentUserId());
|
||||||
@@ -100,14 +104,15 @@ public class CsPqdifPathServiceImpl implements CsPqdifPathService {
|
|||||||
if (param == null) {
|
if (param == null) {
|
||||||
throw new IllegalArgumentException("PQDIF解析结果不能为空");
|
throw new IllegalArgumentException("PQDIF解析结果不能为空");
|
||||||
}
|
}
|
||||||
CsPqdifPathPO pqdifPath = requirePqdifPath(pqdifId);
|
String id = requireNormalPqdifPath(pqdifId);
|
||||||
pqdifPath.setNativeVersion(trimToNull(param.getNativeVersion()));
|
CsPqdifPathPO pqdifPath = new CsPqdifPathPO();
|
||||||
|
pqdifPath.setId(id);
|
||||||
pqdifPath.setRecordCount(param.getRecordCount());
|
pqdifPath.setRecordCount(param.getRecordCount());
|
||||||
pqdifPath.setObservationCount(param.getObservationCount());
|
pqdifPath.setObservationCount(param.getObservationCount());
|
||||||
pqdifPath.setSampleValueCount(param.getSampleValueCount());
|
pqdifPath.setSampleValueCount(param.getSampleValueCount());
|
||||||
pqdifPath.setResult(normalizeResult(param.getResult()));
|
Integer result = normalizeResult(param.getResult());
|
||||||
pqdifPath.setMsg(param.getMsg());
|
pqdifPath.setResult(result);
|
||||||
pqdifPath.setJsonStr(trimToNull(param.getJsonStr()));
|
pqdifPath.setMsg(buildStorageResultMsg(result));
|
||||||
pqdifPath.setUpdateBy(currentUserId());
|
pqdifPath.setUpdateBy(currentUserId());
|
||||||
pqdifPath.setUpdateTime(LocalDateTime.now());
|
pqdifPath.setUpdateTime(LocalDateTime.now());
|
||||||
return csPqdifPathMapper.updateById(pqdifPath) > 0;
|
return csPqdifPathMapper.updateById(pqdifPath) > 0;
|
||||||
@@ -116,7 +121,7 @@ public class CsPqdifPathServiceImpl implements CsPqdifPathService {
|
|||||||
private CsPqdifPathPO buildPqdifPath(CsPqdifPathParam param) {
|
private CsPqdifPathPO buildPqdifPath(CsPqdifPathParam param) {
|
||||||
CsPqdifPathPO pqdifPath = new CsPqdifPathPO();
|
CsPqdifPathPO pqdifPath = new CsPqdifPathPO();
|
||||||
pqdifPath.setName(requireText(param.getName(), "PQDIF名称不能为空"));
|
pqdifPath.setName(requireText(param.getName(), "PQDIF名称不能为空"));
|
||||||
pqdifPath.setPqdifContent(param.getPqdifContent());
|
pqdifPath.setFilePath(trimToNull(param.getFilePath()));
|
||||||
return pqdifPath;
|
return pqdifPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,13 +140,13 @@ public class CsPqdifPathServiceImpl implements CsPqdifPathService {
|
|||||||
return param;
|
return param;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CsPqdifPathPO requirePqdifPath(String pqdifId) {
|
private String requireNormalPqdifPath(String pqdifId) {
|
||||||
String id = requireText(pqdifId, "PQDIF记录ID不能为空");
|
String id = requireText(pqdifId, "PQDIF记录ID不能为空");
|
||||||
CsPqdifPathPO pqdifPath = csPqdifPathMapper.selectById(id);
|
CsPqdifPathDetailVO pqdifPath = csPqdifPathMapper.selectPqdifPathDetailById(id);
|
||||||
if (pqdifPath == null || !Integer.valueOf(STATE_NORMAL).equals(pqdifPath.getState())) {
|
if (pqdifPath == null) {
|
||||||
throw new IllegalArgumentException("PQDIF记录不存在或已删除");
|
throw new IllegalArgumentException("PQDIF记录不存在或已删除");
|
||||||
}
|
}
|
||||||
return pqdifPath;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Integer normalizeResult(Integer result) {
|
private Integer normalizeResult(Integer result) {
|
||||||
@@ -154,6 +159,18 @@ public class CsPqdifPathServiceImpl implements CsPqdifPathService {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private JsonNode buildStorageResultMsg(Integer result) {
|
||||||
|
ObjectNode msg = OBJECT_MAPPER.createObjectNode();
|
||||||
|
if (Integer.valueOf(1).equals(result)) {
|
||||||
|
msg.put("storageResult", "SUCCESS");
|
||||||
|
msg.put("message", "存储成功");
|
||||||
|
} else {
|
||||||
|
msg.put("storageResult", "FAILED");
|
||||||
|
msg.put("message", "存储失败");
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
private String requireText(String value, String message) {
|
private String requireText(String value, String message) {
|
||||||
String text = trimToNull(value);
|
String text = trimToNull(value);
|
||||||
if (text == null) {
|
if (text == null) {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package com.njcn.gather.tool.parsepqdif.service.impl;
|
package com.njcn.gather.tool.parsepqdif.service.impl;
|
||||||
|
|
||||||
|
import com.njcn.gather.tool.parsepqdif.component.PqdifSecondParseComponent;
|
||||||
import com.njcn.gather.tool.parsepqdif.pojo.vo.PqdifParseResponse;
|
import com.njcn.gather.tool.parsepqdif.pojo.vo.PqdifParseResponse;
|
||||||
|
import com.njcn.gather.tool.parsepqdif.pojo.vo.PqdifRecognizeResultVO;
|
||||||
import com.njcn.gather.tool.parsepqdif.reader.PqdifNativeReader;
|
import com.njcn.gather.tool.parsepqdif.reader.PqdifNativeReader;
|
||||||
import com.njcn.gather.tool.parsepqdif.service.ParsePqdifService;
|
import com.njcn.gather.tool.parsepqdif.service.ParsePqdifService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@@ -31,6 +33,7 @@ public class ParsePqdifServiceImpl implements ParsePqdifService {
|
|||||||
private static final String UNKNOWN_FAILED_REASON = "请检查文件内容或原生解析库状态";
|
private static final String UNKNOWN_FAILED_REASON = "请检查文件内容或原生解析库状态";
|
||||||
|
|
||||||
private final PqdifNativeReader pqdifNativeReader;
|
private final PqdifNativeReader pqdifNativeReader;
|
||||||
|
private final PqdifSecondParseComponent pqdifSecondParseComponent;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PqdifParseResponse parse(MultipartFile pqdifFile) {
|
public PqdifParseResponse parse(MultipartFile pqdifFile) {
|
||||||
@@ -56,6 +59,11 @@ public class ParsePqdifServiceImpl implements ParsePqdifService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PqdifRecognizeResultVO parseRecognizable(PqdifParseResponse parseResponse) {
|
||||||
|
return pqdifSecondParseComponent.parseRecognizableData(parseResponse);
|
||||||
|
}
|
||||||
|
|
||||||
private Path createTempPqdifFile(MultipartFile pqdifFile, String suffix) throws Exception {
|
private Path createTempPqdifFile(MultipartFile pqdifFile, String suffix) throws Exception {
|
||||||
// 原生解析库只接收文件路径,因此上传内容需先落到系统临时目录。
|
// 原生解析库只接收文件路径,因此上传内容需先落到系统临时目录。
|
||||||
Path uploadDir = Paths.get(System.getProperty("java.io.tmpdir"), TEMP_DIR_NAME);
|
Path uploadDir = Paths.get(System.getProperty("java.io.tmpdir"), TEMP_DIR_NAME);
|
||||||
|
|||||||
@@ -0,0 +1,151 @@
|
|||||||
|
package com.njcn.gather.tool.parsepqdif;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.njcn.gather.tool.parsepqdif.component.PqdifSecondParseComponent;
|
||||||
|
import com.njcn.gather.tool.parsepqdif.pojo.vo.PqdifParseResponse;
|
||||||
|
import com.njcn.gather.tool.parsepqdif.pojo.vo.PqdifRecognizeResultVO;
|
||||||
|
import com.njcn.gather.tool.parsepqdif.reader.PqdifNativeReader;
|
||||||
|
import com.njcn.gather.tool.parsepqdif.service.ParsePqdifService;
|
||||||
|
import com.njcn.gather.tool.parsepqdif.service.impl.ParsePqdifServiceImpl;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class PqdifDesktopFileTestProgram {
|
||||||
|
|
||||||
|
private static final String PQDIF_FILE_NAME = "PQMonitor_PQM1_20210512_1000_01.pqd";
|
||||||
|
private static final String MULTIPART_PARAM_NAME = "pqdifFile";
|
||||||
|
private static final String SAMPLE_RESOURCE_PATH = "pqdif-samples/" + PQDIF_FILE_NAME;
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
Path pqdifPath = resolvePqdifPath(args);
|
||||||
|
if (!Files.isRegularFile(pqdifPath)) {
|
||||||
|
System.out.println("PQDIF file not found: " + pqdifPath.toAbsolutePath());
|
||||||
|
System.out.println("Usage: java " + PqdifDesktopFileTestProgram.class.getName() + " <pqdif-file-path>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("Parsing PQDIF file: " + pqdifPath.toAbsolutePath());
|
||||||
|
|
||||||
|
ParsePqdifService parsePqdifService = new ParsePqdifServiceImpl(new PqdifNativeReader(), new PqdifSecondParseComponent());
|
||||||
|
PqdifParseResponse response = parsePqdifService.parse(new PathMultipartFile(MULTIPART_PARAM_NAME, pqdifPath));
|
||||||
|
System.out.println("Original parse response:");
|
||||||
|
printResponse(response);
|
||||||
|
|
||||||
|
PqdifRecognizeResultVO recognizableResult = parsePqdifService.parseRecognizable(response);
|
||||||
|
System.out.println("Recognizable parse response:");
|
||||||
|
printResponse(recognizableResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Path resolvePqdifPath(String[] args) {
|
||||||
|
if (args != null && args.length > 0 && args[0] != null && !args[0].trim().isEmpty()) {
|
||||||
|
return Paths.get(args[0].trim()).toAbsolutePath().normalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
Path bundledSample = resolveBundledSamplePath();
|
||||||
|
if (bundledSample != null && Files.isRegularFile(bundledSample)) {
|
||||||
|
return bundledSample;
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultCandidatePaths().stream()
|
||||||
|
.filter(Files::isRegularFile)
|
||||||
|
.findFirst()
|
||||||
|
.orElse(defaultDesktopPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Path resolveBundledSamplePath() {
|
||||||
|
URL resource = PqdifDesktopFileTestProgram.class.getClassLoader().getResource(SAMPLE_RESOURCE_PATH);
|
||||||
|
if (resource == null || !"file".equalsIgnoreCase(resource.getProtocol())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return Paths.get(resource.toURI()).toAbsolutePath().normalize();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Path> defaultCandidatePaths() {
|
||||||
|
return Arrays.asList(
|
||||||
|
Paths.get("tools", "parse-pqdif", "src", "main", "resources", "pqdif-samples", PQDIF_FILE_NAME),
|
||||||
|
Paths.get("src", "main", "resources", "pqdif-samples", PQDIF_FILE_NAME),
|
||||||
|
defaultDesktopPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Path defaultDesktopPath() {
|
||||||
|
return Paths.get(System.getProperty("user.home"), "Desktop", PQDIF_FILE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void printResponse(Object response) throws IOException {
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(response));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class PathMultipartFile implements MultipartFile {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final Path path;
|
||||||
|
|
||||||
|
private PathMultipartFile(String name, Path path) {
|
||||||
|
this.name = name;
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getOriginalFilename() {
|
||||||
|
return path.getFileName().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getContentType() {
|
||||||
|
return "application/octet-stream";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
try {
|
||||||
|
return Files.size(path) == 0;
|
||||||
|
} catch (IOException e) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getSize() {
|
||||||
|
try {
|
||||||
|
return Files.size(path);
|
||||||
|
} catch (IOException e) {
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] getBytes() throws IOException {
|
||||||
|
return Files.readAllBytes(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getInputStream() throws IOException {
|
||||||
|
return Files.newInputStream(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transferTo(File dest) throws IOException {
|
||||||
|
Files.copy(path, dest.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.njcn.gather.tool.parsepqdif.component;
|
||||||
|
|
||||||
|
import com.njcn.gather.tool.parsepqdif.pojo.vo.PqdifParseResponse;
|
||||||
|
import com.njcn.gather.tool.parsepqdif.pojo.vo.PqdifRecognizeResultVO;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
class PqdifSecondParseComponentTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void parseRecognizableDataFormatsStartTimeAsStandard24HourText() {
|
||||||
|
PqdifParseResponse parseResponse = new PqdifParseResponse();
|
||||||
|
parseResponse.setStatus("SUCCESS");
|
||||||
|
parseResponse.setObservations(new ArrayList<PqdifParseResponse.ObservationVO>());
|
||||||
|
|
||||||
|
PqdifParseResponse.ObservationVO observation = new PqdifParseResponse.ObservationVO();
|
||||||
|
observation.setTimeStartText("2026-06-22T15:04:05.123");
|
||||||
|
observation.setChannels(new ArrayList<PqdifParseResponse.ChannelInfoVO>());
|
||||||
|
parseResponse.getObservations().add(observation);
|
||||||
|
|
||||||
|
PqdifRecognizeResultVO result = new PqdifSecondParseComponent().parseRecognizableData(parseResponse);
|
||||||
|
|
||||||
|
assertEquals("2026-06-22 15:04:05", result.getObservations().get(0).getStartTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user