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:
@@ -30,6 +30,9 @@ public class CsIcdPathParam {
|
||||
@ApiModelProperty("ICD类型,1-手动录入的标准ICD,2-手动录入的非标准ICD,3-上游解析传递的标准ICD,4-上游解析传递的非标准ICD")
|
||||
private Integer type;
|
||||
|
||||
@ApiModelProperty("标准ICD引用ID")
|
||||
private String referenceIcdId;
|
||||
|
||||
/**
|
||||
* ICD 存储记录编辑参数。
|
||||
*/
|
||||
|
||||
@@ -189,6 +189,7 @@ public class CsIcdPathServiceImpl implements CsIcdPathService {
|
||||
icdPath.setAngle(param.getAngle());
|
||||
icdPath.setUsePhaseIndex(param.getUsePhaseIndex());
|
||||
icdPath.setType(useDefaultType ? resolveIcdType(param.getType()) : param.getType());
|
||||
icdPath.setReferenceIcdId(trimToNull(param.getReferenceIcdId()));
|
||||
return icdPath;
|
||||
}
|
||||
|
||||
|
||||
@@ -100,6 +100,20 @@ class CsIcdPathServiceImplTest {
|
||||
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
|
||||
void addIcdPathShouldDefaultTypeToManualNonStandard() {
|
||||
CsIcdPathParam param = buildParam("手动录入非标准ICD");
|
||||
|
||||
@@ -55,6 +55,12 @@
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/lib/pqdif-native-basic-bridge-1.0.0-jar-with-dependencies.jar</systemPath>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<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.response.HttpResult;
|
||||
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.PqdifParseResultSaveParam;
|
||||
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.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -42,6 +42,8 @@ public class CsPqdifPathController extends BaseController {
|
||||
|
||||
private final CsPqdifPathService csPqdifPathService;
|
||||
|
||||
private final PqdifFileStorageService pqdifFileStorageService;
|
||||
|
||||
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
|
||||
@ApiOperation("查询PQDIF存储记录列表")
|
||||
@PostMapping("/list")
|
||||
@@ -69,7 +71,7 @@ public class CsPqdifPathController extends BaseController {
|
||||
@RequestPart("request") @Validated CsPqdifPathParam param) {
|
||||
String methodDescribe = getMethodDescribe("addWithFile");
|
||||
LogUtil.njcnDebug(log, "{},开始上传并新增PQDIF存储记录,fileName={}", methodDescribe, resolveFileName(pqdifFile));
|
||||
fillPqdifFile(param, pqdifFile);
|
||||
fillPqdifFilePath(param, pqdifFile);
|
||||
boolean result = csPqdifPathService.addPqdifPath(param);
|
||||
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
|
||||
}
|
||||
@@ -92,7 +94,7 @@ public class CsPqdifPathController extends BaseController {
|
||||
String methodDescribe = getMethodDescribe("updateWithFile");
|
||||
LogUtil.njcnDebug(log, "{},开始上传并编辑PQDIF存储记录,pqdifId={},fileName={}",
|
||||
methodDescribe, param.getId(), resolveFileName(pqdifFile));
|
||||
fillPqdifFile(param, pqdifFile);
|
||||
fillPqdifFilePath(param, pqdifFile);
|
||||
boolean result = csPqdifPathService.updatePqdifPath(param);
|
||||
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
|
||||
}
|
||||
@@ -141,15 +143,8 @@ public class CsPqdifPathController extends BaseController {
|
||||
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
|
||||
}
|
||||
|
||||
private void fillPqdifFile(CsPqdifPathParam param, MultipartFile pqdifFile) {
|
||||
if (pqdifFile == null || pqdifFile.isEmpty()) {
|
||||
throw new IllegalArgumentException("PQDIF文件不能为空");
|
||||
}
|
||||
try {
|
||||
param.setPqdifContent(pqdifFile.getBytes());
|
||||
} catch (IOException ex) {
|
||||
throw new IllegalArgumentException("读取PQDIF文件失败:" + ex.getMessage(), ex);
|
||||
}
|
||||
private void fillPqdifFilePath(CsPqdifPathParam param, MultipartFile pqdifFile) {
|
||||
param.setFilePath(pqdifFileStorageService.save(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.utils.LogUtil;
|
||||
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.web.controller.BaseController;
|
||||
import com.njcn.web.utils.HttpResultUtil;
|
||||
@@ -43,4 +44,17 @@ public class ParsePqdifController extends BaseController {
|
||||
PqdifParseResponse result = parsePqdifService.parse(pqdifFile);
|
||||
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">
|
||||
<id column="id" property="id"/>
|
||||
<result column="name" property="name"/>
|
||||
<result column="nativeVersion" property="nativeVersion"/>
|
||||
<result column="filePath" property="filePath"/>
|
||||
<result column="recordCount" property="recordCount"/>
|
||||
<result column="observationCount" property="observationCount"/>
|
||||
<result column="sampleValueCount" property="sampleValueCount"/>
|
||||
@@ -26,13 +26,12 @@
|
||||
SELECT
|
||||
ID AS id,
|
||||
Name AS name,
|
||||
Native_Version AS nativeVersion,
|
||||
File_Path AS filePath,
|
||||
Record_Count AS recordCount,
|
||||
Observation_Count AS observationCount,
|
||||
Sample_Value_Count AS sampleValueCount,
|
||||
State AS state,
|
||||
Result AS result,
|
||||
Msg AS msg,
|
||||
Create_By AS createBy,
|
||||
Create_Time AS createTime,
|
||||
Update_By AS updateBy,
|
||||
@@ -61,8 +60,7 @@
|
||||
SELECT
|
||||
ID AS id,
|
||||
Name AS name,
|
||||
Json_Str AS jsonStr,
|
||||
Pqdif AS pqdifContent
|
||||
File_Path AS filePath
|
||||
FROM cs_pqdif_path
|
||||
WHERE ID = #{id}
|
||||
AND State = 1
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.njcn.gather.tool.parsepqdif.pojo.param;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
@@ -18,8 +19,9 @@ public class CsPqdifPathParam {
|
||||
@NotBlank(message = "PQDIF名称不能为空")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty("PQDIF文件二进制内容")
|
||||
private byte[] pqdifContent;
|
||||
@ApiModelProperty("PQDIF原始文件存储路径")
|
||||
@JsonIgnore
|
||||
private String filePath;
|
||||
|
||||
/**
|
||||
* PQDIF 存储记录编辑参数。
|
||||
|
||||
@@ -12,9 +12,6 @@ import lombok.Data;
|
||||
@ApiModel("PQDIF解析结果保存参数")
|
||||
public class PqdifParseResultSaveParam {
|
||||
|
||||
@ApiModelProperty("native解析库版本")
|
||||
private String nativeVersion;
|
||||
|
||||
@ApiModelProperty("Record总数")
|
||||
private Long recordCount;
|
||||
|
||||
@@ -30,6 +27,4 @@ public class PqdifParseResultSaveParam {
|
||||
@ApiModelProperty("解析提示、失败原因或解析结论JSON")
|
||||
private JsonNode msg;
|
||||
|
||||
@ApiModelProperty("完整PQDIF解析结果JSON")
|
||||
private String jsonStr;
|
||||
}
|
||||
|
||||
@@ -25,11 +25,8 @@ public class CsPqdifPathPO implements Serializable {
|
||||
@TableField("Name")
|
||||
private String name;
|
||||
|
||||
@TableField("Pqdif")
|
||||
private byte[] pqdifContent;
|
||||
|
||||
@TableField("Native_Version")
|
||||
private String nativeVersion;
|
||||
@TableField("File_Path")
|
||||
private String filePath;
|
||||
|
||||
@TableField("Record_Count")
|
||||
private Long recordCount;
|
||||
@@ -46,9 +43,6 @@ public class CsPqdifPathPO implements Serializable {
|
||||
@TableField(value = "Msg", typeHandler = JsonNodeTypeHandler.class)
|
||||
private JsonNode msg;
|
||||
|
||||
@TableField("Json_Str")
|
||||
private String jsonStr;
|
||||
|
||||
@TableField("State")
|
||||
private Integer state;
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.njcn.gather.tool.parsepqdif.pojo.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
@@ -18,9 +17,6 @@ public class CsPqdifPathDetailVO {
|
||||
@ApiModelProperty("PQDIF名称")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty("完整PQDIF解析结果JSON")
|
||||
private String jsonStr;
|
||||
|
||||
@JsonIgnore
|
||||
private byte[] pqdifContent;
|
||||
@ApiModelProperty("PQDIF原始文件存储路径")
|
||||
private String filePath;
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ public class CsPqdifPathVO {
|
||||
@ApiModelProperty("PQDIF名称")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty("native解析库版本")
|
||||
private String nativeVersion;
|
||||
@ApiModelProperty("PQDIF原始文件存储路径")
|
||||
private String filePath;
|
||||
|
||||
@ApiModelProperty("Record总数")
|
||||
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;
|
||||
|
||||
import com.njcn.gather.tool.parsepqdif.pojo.vo.PqdifParseResponse;
|
||||
import com.njcn.gather.tool.parsepqdif.pojo.vo.PqdifRecognizeResultVO;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
@@ -9,4 +10,6 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
public interface ParsePqdifService {
|
||||
|
||||
PqdifParseResponse parse(MultipartFile pqdifFile);
|
||||
|
||||
PqdifRecognizeResultVO parseRecognizable(PqdifParseResponse parseResponse);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package com.njcn.gather.tool.parsepqdif.service.impl;
|
||||
|
||||
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.node.ObjectNode;
|
||||
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.PqdifParseResultSaveParam;
|
||||
@@ -29,6 +31,8 @@ public class CsPqdifPathServiceImpl implements CsPqdifPathService {
|
||||
|
||||
private static final int STATE_DELETED = 0;
|
||||
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
|
||||
private final CsPqdifPathMapper csPqdifPathMapper;
|
||||
|
||||
@Override
|
||||
@@ -71,7 +75,7 @@ public class CsPqdifPathServiceImpl implements CsPqdifPathService {
|
||||
@Transactional
|
||||
public boolean updatePqdifPath(CsPqdifPathParam.UpdateParam param) {
|
||||
CsPqdifPathParam.UpdateParam checkedParam = requireUpdateParam(param);
|
||||
requirePqdifPath(checkedParam.getId());
|
||||
requireNormalPqdifPath(checkedParam.getId());
|
||||
CsPqdifPathPO pqdifPath = buildPqdifPath(checkedParam);
|
||||
pqdifPath.setId(checkedParam.getId());
|
||||
pqdifPath.setUpdateBy(currentUserId());
|
||||
@@ -100,14 +104,15 @@ public class CsPqdifPathServiceImpl implements CsPqdifPathService {
|
||||
if (param == null) {
|
||||
throw new IllegalArgumentException("PQDIF解析结果不能为空");
|
||||
}
|
||||
CsPqdifPathPO pqdifPath = requirePqdifPath(pqdifId);
|
||||
pqdifPath.setNativeVersion(trimToNull(param.getNativeVersion()));
|
||||
String id = requireNormalPqdifPath(pqdifId);
|
||||
CsPqdifPathPO pqdifPath = new CsPqdifPathPO();
|
||||
pqdifPath.setId(id);
|
||||
pqdifPath.setRecordCount(param.getRecordCount());
|
||||
pqdifPath.setObservationCount(param.getObservationCount());
|
||||
pqdifPath.setSampleValueCount(param.getSampleValueCount());
|
||||
pqdifPath.setResult(normalizeResult(param.getResult()));
|
||||
pqdifPath.setMsg(param.getMsg());
|
||||
pqdifPath.setJsonStr(trimToNull(param.getJsonStr()));
|
||||
Integer result = normalizeResult(param.getResult());
|
||||
pqdifPath.setResult(result);
|
||||
pqdifPath.setMsg(buildStorageResultMsg(result));
|
||||
pqdifPath.setUpdateBy(currentUserId());
|
||||
pqdifPath.setUpdateTime(LocalDateTime.now());
|
||||
return csPqdifPathMapper.updateById(pqdifPath) > 0;
|
||||
@@ -116,7 +121,7 @@ public class CsPqdifPathServiceImpl implements CsPqdifPathService {
|
||||
private CsPqdifPathPO buildPqdifPath(CsPqdifPathParam param) {
|
||||
CsPqdifPathPO pqdifPath = new CsPqdifPathPO();
|
||||
pqdifPath.setName(requireText(param.getName(), "PQDIF名称不能为空"));
|
||||
pqdifPath.setPqdifContent(param.getPqdifContent());
|
||||
pqdifPath.setFilePath(trimToNull(param.getFilePath()));
|
||||
return pqdifPath;
|
||||
}
|
||||
|
||||
@@ -135,13 +140,13 @@ public class CsPqdifPathServiceImpl implements CsPqdifPathService {
|
||||
return param;
|
||||
}
|
||||
|
||||
private CsPqdifPathPO requirePqdifPath(String pqdifId) {
|
||||
private String requireNormalPqdifPath(String pqdifId) {
|
||||
String id = requireText(pqdifId, "PQDIF记录ID不能为空");
|
||||
CsPqdifPathPO pqdifPath = csPqdifPathMapper.selectById(id);
|
||||
if (pqdifPath == null || !Integer.valueOf(STATE_NORMAL).equals(pqdifPath.getState())) {
|
||||
CsPqdifPathDetailVO pqdifPath = csPqdifPathMapper.selectPqdifPathDetailById(id);
|
||||
if (pqdifPath == null) {
|
||||
throw new IllegalArgumentException("PQDIF记录不存在或已删除");
|
||||
}
|
||||
return pqdifPath;
|
||||
return id;
|
||||
}
|
||||
|
||||
private Integer normalizeResult(Integer result) {
|
||||
@@ -154,6 +159,18 @@ public class CsPqdifPathServiceImpl implements CsPqdifPathService {
|
||||
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) {
|
||||
String text = trimToNull(value);
|
||||
if (text == null) {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
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.PqdifRecognizeResultVO;
|
||||
import com.njcn.gather.tool.parsepqdif.reader.PqdifNativeReader;
|
||||
import com.njcn.gather.tool.parsepqdif.service.ParsePqdifService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -31,6 +33,7 @@ public class ParsePqdifServiceImpl implements ParsePqdifService {
|
||||
private static final String UNKNOWN_FAILED_REASON = "请检查文件内容或原生解析库状态";
|
||||
|
||||
private final PqdifNativeReader pqdifNativeReader;
|
||||
private final PqdifSecondParseComponent pqdifSecondParseComponent;
|
||||
|
||||
@Override
|
||||
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 {
|
||||
// 原生解析库只接收文件路径,因此上传内容需先落到系统临时目录。
|
||||
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