package jnpf.elnService.impl;
|
|
import jnpf.elnEntity.field.ElnFieldForms;
|
import jnpf.elnEntity.field.ElnFieldVersionEntity;
|
import jnpf.elnEntity.runtime.ElnRecordFieldValueEntity;
|
import jnpf.exception.DataException;
|
import jnpf.lims.api.model.ElnSourcePropertyRef;
|
import jnpf.lims.api.model.ElnSourceSnapshot;
|
|
import java.time.Instant;
|
import java.util.Date;
|
import java.util.LinkedHashMap;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Objects;
|
|
/** Shared validation for configured snapshots at creation and explicit synchronization. */
|
final class ElnConfiguredSourceValues {
|
private ElnConfiguredSourceValues() { }
|
|
static ElnSourcePropertyRef reference(ElnFieldForms.Read read) {
|
if (read.getPropertyRevision() == null || read.getPropertyRevision() < 1
|
|| read.getProperty() == null || !read.getProperty().matches("[a-zA-Z][a-zA-Z0-9_.-]{0,79}")) {
|
throw new DataException("LIMS 来源固定版本无效");
|
}
|
return new ElnSourcePropertyRef(read.getProperty(), read.getPropertyRevision());
|
}
|
|
static Map<ElnSourcePropertyRef, ElnSourceSnapshot> index(String itemId,
|
List<ElnSourcePropertyRef> requested, List<ElnSourceSnapshot> snapshots) {
|
if (snapshots == null) throw new DataException("LIMS 来源快照响应为空");
|
Map<ElnSourcePropertyRef, ElnSourceSnapshot> result = new LinkedHashMap<>();
|
for (ElnSourceSnapshot snapshot : snapshots) {
|
if (snapshot == null || !Objects.equals(itemId, snapshot.getSourceRef())) {
|
throw new DataException("LIMS 来源快照检验项不一致");
|
}
|
ElnSourcePropertyRef ref = new ElnSourcePropertyRef(snapshot.getPropertyCode(), snapshot.getPropertyRevision());
|
if (!requested.contains(ref) || result.putIfAbsent(ref, snapshot) != null) {
|
throw new DataException("LIMS 来源快照版本不一致或重复");
|
}
|
}
|
if (result.size() != new java.util.HashSet<>(requested).size()) {
|
throw new DataException("LIMS 来源快照缺少固定版本结果");
|
}
|
return result;
|
}
|
|
static void apply(ElnRecordFieldValueEntity value, ElnFieldVersionEntity version, ElnSourceSnapshot snapshot) {
|
if (snapshot == null) throw new DataException("LIMS 来源快照为空");
|
boolean missing = "MISSING".equals(snapshot.getOutcomeCode()) || "NOT_APPLICABLE".equals(snapshot.getOutcomeCode());
|
if (!"SUCCESS".equals(snapshot.getOutcomeCode()) && !missing) {
|
throw new DataException("LIMS 来源取数失败");
|
}
|
if (missing && Integer.valueOf(1).equals(version.getShifouBitian())) {
|
throw new DataException("必填 LIMS 来源缺失或不适用");
|
}
|
if (!Objects.equals(version.getShujuLeixing(), snapshot.getDataType())
|
&& !("CHECKBOX".equals(version.getShujuLeixing()) && "BOOLEAN".equals(snapshot.getDataType()))
|
&& !("TEXT".equals(snapshot.getDataType()) && ("TEXTAREA".equals(version.getShujuLeixing())
|
|| "SELECT".equals(version.getShujuLeixing())))) {
|
throw new DataException("LIMS 来源类型与固定字段版本不兼容");
|
}
|
if (!missing && (snapshot.getValue() == null || snapshot.getValue().trim().isEmpty())) {
|
throw new DataException("LIMS 来源成功结果不能为空");
|
}
|
Date acquiredAt;
|
try { acquiredAt = Date.from(Instant.parse(snapshot.getAcquiredAt())); }
|
catch (RuntimeException invalid) { throw new DataException("LIMS 来源获取时间无效"); }
|
if (missing) {
|
value.setZhiWenben(null);
|
value.setZhiShuzhi(null);
|
value.setZhiRiqi(null);
|
} else if ("DECIMAL".equals(snapshot.getDataType())) {
|
try {
|
java.math.BigDecimal number = new java.math.BigDecimal(snapshot.getValue());
|
java.math.BigDecimal normalized = number.stripTrailingZeros();
|
if (normalized.scale() > 18 || (long) normalized.precision() - normalized.scale() > 20) {
|
throw new DataException("LIMS 来源数值超出快照精度范围,不能舍入保存");
|
}
|
value.setZhiShuzhi(number);
|
}
|
catch (NumberFormatException invalid) { throw new DataException("LIMS 来源数值无效"); }
|
} else if ("DATE".equals(snapshot.getDataType())) {
|
try { value.setZhiRiqi(java.sql.Date.valueOf(java.time.LocalDate.parse(snapshot.getValue()))); }
|
catch (RuntimeException invalid) { throw new DataException("LIMS 来源日期无效"); }
|
} else if ("DATETIME".equals(snapshot.getDataType())) {
|
try {
|
java.time.temporal.TemporalAccessor parsed = java.time.format.DateTimeFormatter.ISO_DATE_TIME
|
.parseBest(snapshot.getValue(), java.time.OffsetDateTime::from, java.time.LocalDateTime::from);
|
if (parsed.get(java.time.temporal.ChronoField.NANO_OF_SECOND) != 0) {
|
throw new DataException("LIMS 来源时间超出快照秒级精度,不能舍入保存");
|
}
|
value.setZhiRiqi(parsed instanceof java.time.OffsetDateTime
|
? Date.from(((java.time.OffsetDateTime) parsed).toInstant())
|
: java.sql.Timestamp.valueOf((java.time.LocalDateTime) parsed));
|
}
|
catch (DataException invalid) { throw invalid; }
|
catch (RuntimeException invalid) { throw new DataException("LIMS 来源时间无效"); }
|
} else if ("BOOLEAN".equals(snapshot.getDataType())) {
|
if (!"true".equals(snapshot.getValue()) && !"false".equals(snapshot.getValue())) {
|
throw new DataException("LIMS 来源布尔值无效");
|
}
|
value.setZhiWenben(snapshot.getValue());
|
} else {
|
value.setZhiWenben(snapshot.getValue());
|
}
|
value.setZhiLaiyuan("LIMS_TASK");
|
value.setYuanShuxing(snapshot.getPropertyCode());
|
value.setYuanShuxingBanben(snapshot.getPropertyRevision());
|
value.setYuanQuzhiZhuangtai(snapshot.getOutcomeCode());
|
value.setYuanQuzhiYuanyin(snapshot.getReasonCode());
|
value.setYuanXueyuan(snapshot.getLineage());
|
value.setYuanYinyongLeixing("LIMS_TASK");
|
value.setYuanYinyongId(snapshot.getSourceRef());
|
value.setYuanHuoquShijian(acquiredAt);
|
}
|
}
|