package jnpf.elnService.template.impl;
|
|
import jnpf.elnEntity.template.ElnTemplateStageEntity;
|
import jnpf.elnEntity.template.ElnTemplateStepEntity;
|
import jnpf.elnEntity.template.ElnTemplateForms;
|
import jnpf.elnEntity.template.ElnTemplateBindingEntity;
|
import jnpf.elnEntity.template.ElnTemplateRepeatGroupEntity;
|
import jnpf.elnEntity.template.ElnTemplateVersionEntity;
|
import jnpf.elnEntity.template.ElnTemplateVos;
|
import org.junit.Test;
|
|
import java.util.ArrayList;
|
import java.util.Arrays;
|
import java.util.List;
|
import java.util.Collections;
|
import java.util.LinkedHashMap;
|
import java.util.Map;
|
|
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.fail;
|
|
public class ElnTemplateStepServiceImplTest {
|
|
@Test
|
public void flattensLegacyStagesIntoStableGlobalStepOrder() {
|
MemoryStore store = new MemoryStore();
|
store.template = template("template-1", "DRAFT");
|
store.stages.add(stage("stage-2", "样品处理", 2));
|
store.stages.add(stage("stage-1", "实验准备", 1));
|
store.steps.add(step("step-3", "stage-2", "结果记录", 1));
|
store.steps.add(step("step-2", "stage-1", "环境确认", 2));
|
store.steps.add(step("step-1", "stage-1", "仪器准备", 1));
|
store.steps.add(step("step-4", null, "未分阶段记录", 1));
|
ElnTemplateStepServiceImpl service = new ElnTemplateStepServiceImpl(
|
store, () -> new ElnTemplateStepServiceImpl.UserContext("tenant-1", "user-1"));
|
|
ElnTemplateVos.StepConfiguration result = service.configuration("template-1");
|
|
assertFalse(result.isSingleStep());
|
assertEquals(Arrays.asList("step-1", "step-2", "step-3", "step-4"), stepIds(result.getSteps()));
|
assertEquals(Integer.valueOf(1), result.getSteps().get(0).getOrder());
|
assertEquals(Integer.valueOf(2), result.getSteps().get(1).getOrder());
|
assertEquals(Integer.valueOf(3), result.getSteps().get(2).getOrder());
|
}
|
|
@Test
|
public void rejectsTemplateWithoutAnyStep() {
|
MemoryStore store = new MemoryStore();
|
store.template = template("template-1", "DRAFT");
|
ElnTemplateStepServiceImpl service = new ElnTemplateStepServiceImpl(
|
store, () -> new ElnTemplateStepServiceImpl.UserContext("tenant-1", "user-1"));
|
|
try {
|
service.configuration("template-1");
|
fail("每个模板版本必须至少有一个步骤");
|
} catch (jnpf.exception.DataException expected) {
|
assertEquals("模板版本未配置步骤", expected.getMessage());
|
}
|
}
|
|
@Test
|
public void aggregatesEffectiveControlAndRepeatGroupOwnershipForFill() {
|
MemoryStore store = new MemoryStore();
|
store.template = template("template-1", "PUBLISHED");
|
store.steps.add(step("step-1", null, "准备", 1));
|
store.steps.add(step("step-2", null, "记录", 2));
|
ElnTemplateBindingEntity primary = binding("primary-1", "template-1", "step-1");
|
primary.setKongjianBiaoqian("eln.field.result");
|
ElnTemplateBindingEntity reference = binding("reference-1", "template-1", null);
|
reference.setKongjianJuese("REFERENCE");
|
reference.setYinyongShiliId("primary-1");
|
reference.setKongjianBiaoqian("eln.ref.result.1");
|
ElnTemplateBindingEntity repeat = binding("repeat-1", "template-1", null);
|
repeat.setKongjianJuese("REPEAT");
|
repeat.setRepeatGroupCode("samples");
|
repeat.setKongjianBiaoqian("eln.repeat.samples.prototype.result");
|
store.bindings.add(primary);
|
store.bindings.add(reference);
|
store.bindings.add(repeat);
|
store.repeatGroups.add(repeatGroup(
|
"group-1", "template-1", "samples", "step-2"));
|
ElnTemplateStepServiceImpl service = new ElnTemplateStepServiceImpl(
|
store, () -> new ElnTemplateStepServiceImpl.UserContext("tenant-1", "user-1"));
|
|
ElnTemplateVos.StepFillStructure result = service.fillStructure(
|
"tenant-1", "template-1");
|
|
assertFalse(result.getConfiguration().isSingleStep());
|
assertEquals("step-1", result.getControlSteps().get("eln.field.result"));
|
assertEquals("step-1", result.getControlSteps().get("eln.ref.result.1"));
|
assertEquals("step-2", result.getControlSteps().get(
|
"eln.repeat.samples.prototype.result"));
|
assertEquals("step-2", result.getRepeatGroupSteps().get("samples"));
|
}
|
|
@Test
|
public void savesOrderedDraftStepsWithoutRebuildingExistingIdentity() {
|
MemoryStore store = new MemoryStore();
|
store.template = template("template-1", "DRAFT");
|
store.steps.add(step("step-1", null, "原步骤", 1));
|
ElnTemplateStepServiceImpl service = new ElnTemplateStepServiceImpl(
|
store, () -> new ElnTemplateStepServiceImpl.UserContext("tenant-1", "user-1"),
|
new SequenceIds());
|
ElnTemplateForms.SaveStepConfiguration form = new ElnTemplateForms.SaveStepConfiguration();
|
ElnTemplateForms.Step existing = new ElnTemplateForms.Step();
|
existing.setId("step-1");
|
existing.setName("准备");
|
ElnTemplateForms.Step added = new ElnTemplateForms.Step();
|
added.setName("检测");
|
form.setSteps(Arrays.asList(existing, added));
|
|
ElnTemplateVos.StepConfiguration result = service.save("template-1", form);
|
|
assertEquals(Arrays.asList("step-1", "generated-1"), stepIds(result.getSteps()));
|
assertEquals(Arrays.asList("准备", "检测"), stepNames(result.getSteps()));
|
assertEquals(Integer.valueOf(1), result.getSteps().get(0).getOrder());
|
assertEquals(Integer.valueOf(2), result.getSteps().get(1).getOrder());
|
}
|
|
@Test
|
public void releasesActiveUniqueSlotsBeforeSwappingLegacyStagedSteps() {
|
MemoryStore store = new MemoryStore();
|
store.template = template("template-1", "DRAFT");
|
store.stages.add(stage("stage-1", "阶段甲", 1));
|
store.stages.add(stage("stage-2", "阶段乙", 2));
|
store.steps.add(step("step-1", "stage-1", "准备", 1));
|
store.steps.add(step("step-2", "stage-2", "检测", 2));
|
ElnTemplateStepServiceImpl service = new ElnTemplateStepServiceImpl(
|
store, () -> new ElnTemplateStepServiceImpl.UserContext("tenant-1", "user-1"));
|
ElnTemplateForms.SaveStepConfiguration form = new ElnTemplateForms.SaveStepConfiguration();
|
ElnTemplateForms.Step firstStep = new ElnTemplateForms.Step();
|
firstStep.setId("step-2");
|
firstStep.setName("准备");
|
ElnTemplateForms.Step secondStep = new ElnTemplateForms.Step();
|
secondStep.setId("step-1");
|
secondStep.setName("检测");
|
form.setSteps(Arrays.asList(firstStep, secondStep));
|
|
ElnTemplateVos.StepConfiguration result = service.save("template-1", form);
|
|
assertTrue(store.stepUniquenessReleased);
|
assertEquals(Arrays.asList("step-2", "step-1"), stepIds(result.getSteps()));
|
assertNull(store.steps.get(0).getJieduanId());
|
assertNull(store.steps.get(1).getJieduanId());
|
}
|
|
@Test
|
public void migratesPrimaryBindingsAndRepeatGroupsBeforeDeletingStep() {
|
MemoryStore store = new MemoryStore();
|
store.template = template("template-1", "DRAFT");
|
store.steps.add(step("step-1", null, "旧步骤", 1));
|
store.steps.add(step("step-2", null, "目标步骤", 2));
|
ElnTemplateBindingEntity primary = new ElnTemplateBindingEntity();
|
primary.setId("binding-1");
|
primary.setMubanId("template-1");
|
primary.setKongjianJuese("PRIMARY");
|
primary.setBangdingZhuangtai("ACTIVE");
|
primary.setStepId("step-1");
|
primary.setFDeleteMark(0);
|
store.bindings.add(primary);
|
ElnTemplateRepeatGroupEntity group = new ElnTemplateRepeatGroupEntity();
|
group.setId("group-1");
|
group.setMubanId("template-1");
|
group.setRepeatGroupCode("results");
|
group.setStepId("step-1");
|
group.setFDeleteMark(0);
|
store.repeatGroups.add(group);
|
ElnTemplateStepServiceImpl service = new ElnTemplateStepServiceImpl(
|
store, () -> new ElnTemplateStepServiceImpl.UserContext("tenant-1", "user-1"),
|
new SequenceIds());
|
ElnTemplateForms.SaveStepConfiguration form = new ElnTemplateForms.SaveStepConfiguration();
|
ElnTemplateForms.Step kept = new ElnTemplateForms.Step();
|
kept.setId("step-2");
|
kept.setName("目标步骤");
|
form.setSteps(Collections.singletonList(kept));
|
Map<String, String> migrations = new LinkedHashMap<>();
|
migrations.put("step-1", "step-2");
|
form.setStepMigrations(migrations);
|
|
ElnTemplateVos.StepConfiguration result = service.save("template-1", form);
|
|
assertEquals(Collections.singletonList("step-2"), stepIds(result.getSteps()));
|
assertEquals("step-2", primary.getStepId());
|
assertEquals("step-2", group.getStepId());
|
assertEquals(Integer.valueOf(1), store.steps.get(0).getFDeleteMark());
|
}
|
|
@Test
|
public void copiesVersionStructureAndRemapsCopiedOwnership() {
|
MemoryStore store = new MemoryStore();
|
ElnTemplateStageEntity sourceStage = stage("source-stage", "检测", 1);
|
sourceStage.setMubanId("source-template");
|
store.stages.add(sourceStage);
|
ElnTemplateStepEntity sourceFirst = step("source-step-1", "source-stage", "准备", 1);
|
sourceFirst.setMubanId("source-template");
|
ElnTemplateStepEntity sourceSecond = step("source-step-2", "source-stage", "记录", 2);
|
sourceSecond.setMubanId("source-template");
|
store.steps.add(sourceFirst);
|
store.steps.add(sourceSecond);
|
ElnTemplateStepEntity targetDefault = step("target-default", null, "实验步骤", 1);
|
targetDefault.setMubanId("target-template");
|
store.steps.add(targetDefault);
|
ElnTemplateBindingEntity sourceBinding = binding(
|
"source-binding", "source-template", "source-step-1");
|
ElnTemplateBindingEntity targetBinding = binding(
|
"target-binding", "target-template", null);
|
targetBinding.setLaiyuanBangdingId("source-binding");
|
store.bindings.add(sourceBinding);
|
store.bindings.add(targetBinding);
|
ElnTemplateRepeatGroupEntity sourceGroup = repeatGroup(
|
"source-group", "source-template", "results", "source-step-2");
|
ElnTemplateRepeatGroupEntity targetGroup = repeatGroup(
|
"target-group", "target-template", "results", null);
|
store.repeatGroups.add(sourceGroup);
|
store.repeatGroups.add(targetGroup);
|
ElnTemplateStepServiceImpl service = new ElnTemplateStepServiceImpl(
|
store, () -> new ElnTemplateStepServiceImpl.UserContext("tenant-1", "user-1"),
|
new SequenceIds());
|
|
service.copyForVersion("tenant-1", "source-template", "target-template");
|
|
assertEquals("target-default", targetBinding.getStepId());
|
assertEquals("generated-1", targetGroup.getStepId());
|
assertEquals("source-step-1", targetDefault.getLaiyuanBuzhouId());
|
assertNull(targetDefault.getJieduanId());
|
assertEquals(Integer.valueOf(1), targetDefault.getPaixu());
|
}
|
|
@Test
|
public void publishValidationRejectsUnassignedPrimaryAndEmptyStep() {
|
MemoryStore store = new MemoryStore();
|
store.steps.add(step("step-1", null, "准备", 1));
|
store.steps.add(step("step-2", null, "记录", 2));
|
store.bindings.add(binding("binding-1", "template-1", null));
|
store.repeatGroups.add(repeatGroup(
|
"group-1", "template-1", "results", "step-2"));
|
ElnTemplateStepServiceImpl service = new ElnTemplateStepServiceImpl(
|
store, () -> new ElnTemplateStepServiceImpl.UserContext("tenant-1", "user-1"),
|
new SequenceIds());
|
|
List<ElnTemplateVos.Diagnostic> diagnostics = service.validate(
|
"tenant-1", "template-1", null);
|
|
assertTrue(codes(diagnostics).contains("UNASSIGNED_PRIMARY_BINDING"));
|
assertTrue(codes(diagnostics).contains("EMPTY_STEP"));
|
}
|
|
@Test
|
public void resolvesMissingAssignmentOnlyForSingleStepTemplate() {
|
MemoryStore store = new MemoryStore();
|
store.steps.add(step("step-1", null, "实验步骤", 1));
|
ElnTemplateStepServiceImpl service = new ElnTemplateStepServiceImpl(
|
store, () -> new ElnTemplateStepServiceImpl.UserContext("tenant-1", "user-1"),
|
new SequenceIds());
|
|
assertEquals("step-1", service.resolveAssignment(
|
"tenant-1", "template-1", null));
|
|
store.steps.add(step("step-2", null, "记录", 2));
|
try {
|
service.resolveAssignment("tenant-1", "template-1", null);
|
fail("多步骤模板必须显式选择步骤");
|
} catch (jnpf.exception.DataException expected) {
|
assertEquals("多步骤模板必须选择当前步骤", expected.getMessage());
|
}
|
}
|
|
private static ElnTemplateVersionEntity template(String id, String status) {
|
ElnTemplateVersionEntity entity = new ElnTemplateVersionEntity();
|
entity.setId(id);
|
entity.setFTenantId("tenant-1");
|
entity.setBizStatus(status);
|
entity.setFDeleteMark(0);
|
return entity;
|
}
|
|
private static ElnTemplateStageEntity stage(String id, String name, int order) {
|
ElnTemplateStageEntity entity = new ElnTemplateStageEntity();
|
entity.setId(id);
|
entity.setFTenantId("tenant-1");
|
entity.setMubanId("template-1");
|
entity.setJieduanMingcheng(name);
|
entity.setPaixu(order);
|
entity.setFDeleteMark(0);
|
return entity;
|
}
|
|
private static ElnTemplateStepEntity step(String id, String stageId, String name, int order) {
|
ElnTemplateStepEntity entity = new ElnTemplateStepEntity();
|
entity.setId(id);
|
entity.setFTenantId("tenant-1");
|
entity.setMubanId("template-1");
|
entity.setJieduanId(stageId);
|
entity.setBuzhouMingcheng(name);
|
entity.setPaixu(order);
|
entity.setFDeleteMark(0);
|
return entity;
|
}
|
|
private static ElnTemplateBindingEntity binding(
|
String id, String templateId, String stepId) {
|
ElnTemplateBindingEntity entity = new ElnTemplateBindingEntity();
|
entity.setId(id);
|
entity.setFTenantId("tenant-1");
|
entity.setMubanId(templateId);
|
entity.setKongjianJuese("PRIMARY");
|
entity.setBangdingZhuangtai("ACTIVE");
|
entity.setStepId(stepId);
|
entity.setFDeleteMark(0);
|
return entity;
|
}
|
|
private static ElnTemplateRepeatGroupEntity repeatGroup(
|
String id, String templateId, String code, String stepId) {
|
ElnTemplateRepeatGroupEntity entity = new ElnTemplateRepeatGroupEntity();
|
entity.setId(id);
|
entity.setFTenantId("tenant-1");
|
entity.setMubanId(templateId);
|
entity.setRepeatGroupCode(code);
|
entity.setStepId(stepId);
|
entity.setFDeleteMark(0);
|
return entity;
|
}
|
|
private static List<String> stepIds(List<ElnTemplateVos.Step> steps) {
|
List<String> result = new ArrayList<>();
|
for (ElnTemplateVos.Step step : steps) result.add(step.getId());
|
return result;
|
}
|
|
private static List<String> stepNames(List<ElnTemplateVos.Step> steps) {
|
List<String> result = new ArrayList<>();
|
for (ElnTemplateVos.Step step : steps) result.add(step.getName());
|
return result;
|
}
|
|
private static List<String> codes(List<ElnTemplateVos.Diagnostic> diagnostics) {
|
List<String> result = new ArrayList<>();
|
for (ElnTemplateVos.Diagnostic item : diagnostics) result.add(item.getCode());
|
return result;
|
}
|
|
private static final class SequenceIds implements java.util.function.Supplier<String> {
|
private int next;
|
@Override public String get() { return "generated-" + (++next); }
|
}
|
|
private static final class MemoryStore implements ElnTemplateStepServiceImpl.Store {
|
private ElnTemplateVersionEntity template;
|
private final List<ElnTemplateStageEntity> stages = new ArrayList<>();
|
private final List<ElnTemplateStepEntity> steps = new ArrayList<>();
|
private final List<ElnTemplateBindingEntity> bindings = new ArrayList<>();
|
private final List<ElnTemplateRepeatGroupEntity> repeatGroups = new ArrayList<>();
|
private boolean stepUniquenessReleased;
|
|
@Override public ElnTemplateVersionEntity findTemplate(String tenantId, String templateId) {
|
return template;
|
}
|
@Override public ElnTemplateVersionEntity findTemplateForUpdate(
|
String tenantId, String templateId) {
|
return template;
|
}
|
@Override public List<ElnTemplateStageEntity> listStages(String tenantId, String templateId) {
|
List<ElnTemplateStageEntity> result = new ArrayList<>();
|
for (ElnTemplateStageEntity stage : stages) {
|
if (templateId.equals(stage.getMubanId())
|
&& !Integer.valueOf(1).equals(stage.getFDeleteMark())) result.add(stage);
|
}
|
return result;
|
}
|
@Override public List<ElnTemplateStepEntity> listSteps(String tenantId, String templateId) {
|
List<ElnTemplateStepEntity> result = new ArrayList<>();
|
for (ElnTemplateStepEntity step : steps) {
|
if (templateId.equals(step.getMubanId())
|
&& !Integer.valueOf(1).equals(step.getFDeleteMark())) result.add(step);
|
}
|
return result;
|
}
|
@Override public List<ElnTemplateBindingEntity> listBindings(
|
String tenantId, String templateId) {
|
List<ElnTemplateBindingEntity> result = new ArrayList<>();
|
for (ElnTemplateBindingEntity binding : bindings) {
|
if (templateId.equals(binding.getMubanId())) result.add(binding);
|
}
|
return result;
|
}
|
@Override public List<ElnTemplateRepeatGroupEntity> listRepeatGroups(
|
String tenantId, String templateId) {
|
List<ElnTemplateRepeatGroupEntity> result = new ArrayList<>();
|
for (ElnTemplateRepeatGroupEntity group : repeatGroups) {
|
if (templateId.equals(group.getMubanId())) result.add(group);
|
}
|
return result;
|
}
|
@Override public void releaseStepUniqueness(String tenantId, String templateId) {
|
stepUniquenessReleased = true;
|
}
|
@Override public void insertStep(ElnTemplateStepEntity entity) { steps.add(entity); }
|
@Override public void updateStep(ElnTemplateStepEntity entity) {
|
for (int i = 0; i < steps.size(); i++) {
|
if (steps.get(i).getId().equals(entity.getId())) {
|
steps.set(i, entity);
|
return;
|
}
|
}
|
}
|
@Override public void updateBindingStep(ElnTemplateBindingEntity entity) { }
|
@Override public void updateRepeatGroupStep(ElnTemplateRepeatGroupEntity entity) { }
|
}
|
}
|