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 index(String itemId, List requested, List snapshots) { if (snapshots == null) throw new DataException("LIMS 来源快照响应为空"); Map 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); } }