package jnpf.elnService.formula;
|
|
import jnpf.elnEntity.field.ElnFieldVersionEntity;
|
import jnpf.elnEntity.formula.ElnFormulaDefEntity;
|
import jnpf.elnEntity.formula.ElnFormulaParameterSlotEntity;
|
import jnpf.elnEntity.formula.ElnFormulaVersionEntity;
|
import jnpf.elnEntity.formula.ElnTemplateFormulaBindingEntity;
|
import jnpf.elnEntity.template.ElnTemplateBindingEntity;
|
import jnpf.elnEntity.template.ElnTemplateVos;
|
import jnpf.elnService.formula.impl.FormulaFieldBindingDependencyValidator;
|
import jnpf.elnService.formula.impl.FormulaTemplatePublishValidator;
|
import jnpf.elnService.template.docx.DocxControlSnapshot;
|
import org.junit.Test;
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import java.lang.reflect.Constructor;
|
import java.util.Arrays;
|
import java.util.Collections;
|
import java.util.LinkedHashMap;
|
import java.util.List;
|
import java.util.Map;
|
|
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertTrue;
|
|
public class FormulaTemplateExtensionsTest {
|
|
@Test
|
public void fieldDependencyValidatorMarksProductionConstructorForSpringInjection() {
|
Constructor<?> production = null;
|
for (Constructor<?> constructor : FormulaFieldBindingDependencyValidator.class.getConstructors()) {
|
if (constructor.getAnnotation(Autowired.class) != null) production = constructor;
|
}
|
assertNotNull("多 public 构造器时生产构造器必须显式 @Autowired", production);
|
}
|
|
@Test
|
public void publishValidatorMarksProductionConstructorForSpringInjection() {
|
Constructor<?> production = null;
|
for (Constructor<?> constructor : FormulaTemplatePublishValidator.class.getConstructors()) {
|
if (constructor.getAnnotation(Autowired.class) != null) production = constructor;
|
}
|
assertNotNull("多 public 构造器时生产构造器必须显式 @Autowired", production);
|
}
|
|
@Test
|
public void fieldDependencyValidatorRejectsIncompatibleUpgradeRemovalAndPromotion() {
|
ExtensionStore store = new ExtensionStore();
|
FormulaFieldBindingDependencyValidator validator =
|
new FormulaFieldBindingDependencyValidator(store);
|
|
assertCode(validator.validateUpgrade("tenant", "template",
|
Collections.singleton("input"), "target-text"), "FORMULA_FIELD_TYPE_MISMATCH");
|
assertCode(validator.validateRemoval("tenant", "template",
|
Collections.singleton("result")), "FORMULA_FIELD_IN_USE");
|
assertCode(validator.validatePromotion("tenant", "template", "result", "result-ref"),
|
"FORMULA_FIELD_IN_USE");
|
assertCode(validator.validateCheckboxGroup("tenant", "template", "result"),
|
"CHECKBOX_GROUP_FORMULA_RESULT_READ_ONLY");
|
}
|
|
@Test
|
public void publishValidatorRejectsPendingAndResultLockMismatch() {
|
ExtensionStore store = new ExtensionStore();
|
FormulaTemplatePublishValidator validator = new FormulaTemplatePublishValidator(
|
store, (tenantId, fileId) -> Collections.singletonList(
|
new DocxControlSnapshot("eln.field.result", null, null, "TEXT",
|
"PRIMARY", "word/document.xml", "OK", Collections.emptyMap())),
|
new FormulaDependencyGraph());
|
|
store.formulaBinding.setBangdingZhuangtai("PENDING");
|
assertCode(validator.validate("tenant", "template", attachment("file.docx")),
|
"PENDING_FORMULA_BINDING");
|
|
store.formulaBinding.setBangdingZhuangtai("ACTIVE");
|
assertCode(validator.validate("tenant", "template", attachment("file.docx")),
|
"FORMULA_RESULT_LOCK_MISMATCH");
|
}
|
|
@Test
|
public void publishValidatorDoesNotTreatPendingResultLocksAsOrphans() {
|
ExtensionStore store = new ExtensionStore();
|
store.formulaBinding.setBangdingZhuangtai("PENDING");
|
FormulaTemplatePublishValidator validator = new FormulaTemplatePublishValidator(
|
store, (tenantId, fileId) -> Arrays.asList(
|
locked("eln.field.result"), locked("eln.field.result-ref")),
|
new FormulaDependencyGraph());
|
|
List<ElnTemplateVos.Diagnostic> diagnostics = validator.validate(
|
"tenant", "template", attachment("file.docx"));
|
|
assertCode(diagnostics, "PENDING_FORMULA_BINDING");
|
assertNoCode(diagnostics, "FORMULA_RESULT_LOCK_MISMATCH");
|
}
|
|
@Test
|
public void publishValidatorIgnoresLockedControlsOutsideFieldBindings() {
|
ExtensionStore store = new ExtensionStore();
|
FormulaTemplatePublishValidator validator = new FormulaTemplatePublishValidator(
|
store, (tenantId, fileId) -> Arrays.asList(
|
locked("eln.field.result"), locked("eln.field.result-ref"),
|
locked("document.protected.control")),
|
new FormulaDependencyGraph());
|
|
List<ElnTemplateVos.Diagnostic> diagnostics = validator.validate(
|
"tenant", "template", attachment("file.docx"));
|
|
assertNoCode(diagnostics, "FORMULA_RESULT_LOCK_MISMATCH");
|
}
|
|
@Test
|
public void publishValidatorRequiresLocksOnlyForActiveReferences() {
|
ExtensionStore store = new ExtensionStore();
|
store.fields.get("result-ref").setBangdingZhuangtai("REMOVED");
|
FormulaTemplatePublishValidator validator = new FormulaTemplatePublishValidator(
|
store, (tenantId, fileId) -> Collections.singletonList(
|
locked("eln.field.result")), new FormulaDependencyGraph());
|
|
List<ElnTemplateVos.Diagnostic> diagnostics = validator.validate(
|
"tenant", "template", attachment("file.docx"));
|
|
assertNoCode(diagnostics, "FORMULA_RESULT_LOCK_MISMATCH");
|
}
|
|
@Test
|
public void publishValidatorRejectsParameterAndResultBindingsFromAnotherTemplate() {
|
ExtensionStore store = new ExtensionStore();
|
store.fields.get("input").setMubanId("other-template");
|
store.fields.get("result").setMubanId("other-template");
|
FormulaTemplatePublishValidator validator = new FormulaTemplatePublishValidator(
|
store, (tenantId, fileId) -> Collections.singletonList(
|
locked("eln.field.result-ref")), new FormulaDependencyGraph());
|
|
List<ElnTemplateVos.Diagnostic> diagnostics = validator.validate(
|
"tenant", "template", attachment("file.docx"));
|
|
assertEquals(2, diagnostics.stream().filter(item ->
|
"FORMULA_BINDING_TEMPLATE_MISMATCH".equals(item.getCode())).count());
|
}
|
|
@Test
|
public void publishValidatorRejectsCrossTemplateBindingsWhenFormulaVersionIsMissing() {
|
ExtensionStore store = new ExtensionStore();
|
store.formulaBinding.setGongshiBanbenId("missing-version");
|
store.fields.get("input").setMubanId("other-template");
|
store.fields.get("result").setMubanId("other-template");
|
FormulaTemplatePublishValidator validator = new FormulaTemplatePublishValidator(
|
store, (tenantId, fileId) -> Collections.singletonList(
|
locked("eln.field.result-ref")), new FormulaDependencyGraph());
|
|
List<ElnTemplateVos.Diagnostic> diagnostics = validator.validate(
|
"tenant", "template", attachment("file.docx"));
|
|
assertEquals(2, diagnostics.stream().filter(item ->
|
"FORMULA_BINDING_TEMPLATE_MISMATCH".equals(item.getCode())).count());
|
}
|
|
@Test
|
public void publishValidatorRejectsCrossTemplateBindingInExtraParameterMapping() {
|
ExtensionStore store = new ExtensionStore();
|
store.addField("extra", "extra-version", "DECIMAL", "PRIMARY", null);
|
store.fields.get("extra").setMubanId("other-template");
|
Map<String, String> mapping = new LinkedHashMap<>();
|
mapping.put("amount", "input");
|
mapping.put("extra", "extra");
|
store.formulaBinding.setCanshuYingshe(mapping);
|
FormulaTemplatePublishValidator validator = new FormulaTemplatePublishValidator(
|
store, (tenantId, fileId) -> Arrays.asList(
|
locked("eln.field.result"), locked("eln.field.result-ref")),
|
new FormulaDependencyGraph());
|
|
List<ElnTemplateVos.Diagnostic> diagnostics = validator.validate(
|
"tenant", "template", attachment("file.docx"));
|
|
assertEquals(1, diagnostics.stream().filter(item ->
|
"FORMULA_BINDING_TEMPLATE_MISMATCH".equals(item.getCode())).count());
|
}
|
|
@Test
|
public void publishValidatorRejectsVersionOwnedByAnotherFormulaDefinition() {
|
ExtensionStore store = new ExtensionStore();
|
store.formulaVersion.setGongshiDingyiId("other-definition");
|
FormulaTemplatePublishValidator validator = new FormulaTemplatePublishValidator(
|
store, (tenantId, fileId) -> Arrays.asList(
|
locked("eln.field.result"), locked("eln.field.result-ref")),
|
new FormulaDependencyGraph());
|
|
List<ElnTemplateVos.Diagnostic> diagnostics = validator.validate(
|
"tenant", "template", attachment("file.docx"));
|
|
assertEquals(1, diagnostics.stream().filter(item ->
|
"FORMULA_DEFINITION_VERSION_MISMATCH".equals(item.getCode())).count());
|
}
|
|
@Test
|
public void publishValidatorRejectsDefinitionWithUnexpectedIdentity() {
|
ExtensionStore store = new ExtensionStore();
|
store.definition.setId("other-definition");
|
FormulaTemplatePublishValidator validator = new FormulaTemplatePublishValidator(
|
store, (tenantId, fileId) -> Arrays.asList(
|
locked("eln.field.result"), locked("eln.field.result-ref")),
|
new FormulaDependencyGraph());
|
|
List<ElnTemplateVos.Diagnostic> diagnostics = validator.validate(
|
"tenant", "template", attachment("file.docx"));
|
|
assertEquals(1, diagnostics.stream().filter(item ->
|
"FORMULA_DEFINITION_VERSION_MISMATCH".equals(item.getCode())).count());
|
}
|
|
private static void assertCode(List<ElnTemplateVos.Diagnostic> diagnostics, String code) {
|
assertTrue("缺少诊断: " + code,
|
diagnostics.stream().anyMatch(item -> code.equals(item.getCode())));
|
}
|
|
private static void assertNoCode(List<ElnTemplateVos.Diagnostic> diagnostics, String code) {
|
assertTrue("不应存在诊断: " + code,
|
diagnostics.stream().noneMatch(item -> code.equals(item.getCode())));
|
}
|
|
private static DocxControlSnapshot locked(String tag) {
|
return new DocxControlSnapshot(tag, null, "sdtContentLocked", "TEXT",
|
"PRIMARY", "word/document.xml", "OK", Collections.emptyMap());
|
}
|
|
private static String attachment(String fileId) {
|
return "[{\"fileId\":\"" + fileId + "\",\"fileExtension\":\"docx\"}]";
|
}
|
|
private static final class ExtensionStore implements
|
FormulaFieldBindingDependencyValidator.Store,
|
FormulaTemplatePublishValidator.Store {
|
private final ElnTemplateFormulaBindingEntity formulaBinding = new ElnTemplateFormulaBindingEntity();
|
private final Map<String, ElnTemplateBindingEntity> fields = new LinkedHashMap<>();
|
private final Map<String, ElnFieldVersionEntity> fieldVersions = new LinkedHashMap<>();
|
private final ElnFormulaVersionEntity formulaVersion = new ElnFormulaVersionEntity();
|
private final ElnFormulaDefEntity definition = new ElnFormulaDefEntity();
|
private final ElnFormulaParameterSlotEntity slot = new ElnFormulaParameterSlotEntity();
|
|
private ExtensionStore() {
|
formulaBinding.setId("formula-binding"); formulaBinding.setFTenantId("tenant");
|
formulaBinding.setMubanId("template"); formulaBinding.setGongshiDingyiId("definition");
|
formulaBinding.setGongshiBanbenId("version");
|
formulaBinding.setCanshuYingshe(Collections.singletonMap("amount", "input"));
|
formulaBinding.setJieguoBangdingId("result"); formulaBinding.setBangdingZhuangtai("ACTIVE");
|
definition.setId("definition"); definition.setBizEnabled("enabled");
|
formulaVersion.setId("version"); formulaVersion.setGongshiDingyiId("definition");
|
formulaVersion.setBizStatus("PUBLISHED"); formulaVersion.setJieguoLeixing("DECIMAL");
|
slot.setCanshuBianma("amount"); slot.setShujuLeixing("DECIMAL");
|
addField("input", "input-version", "DECIMAL", "PRIMARY", null);
|
addField("result", "result-version", "DECIMAL", "PRIMARY", null);
|
addField("result-ref", "result-version", "DECIMAL", "REFERENCE", "result");
|
ElnFieldVersionEntity target = new ElnFieldVersionEntity();
|
target.setId("target-text"); target.setShujuLeixing("TEXT");
|
fieldVersions.put(target.getId(), target);
|
}
|
|
private void addField(String id, String versionId, String type, String role, String primary) {
|
ElnTemplateBindingEntity binding = new ElnTemplateBindingEntity();
|
binding.setId(id); binding.setMubanId("template"); binding.setZiduanBanbenId(versionId);
|
binding.setKongjianBiaoqian("eln.field." + id); binding.setKongjianJuese(role);
|
binding.setYinyongShiliId(primary); binding.setBangdingZhuangtai("ACTIVE");
|
fields.put(id, binding);
|
if (!fieldVersions.containsKey(versionId)) {
|
ElnFieldVersionEntity version = new ElnFieldVersionEntity();
|
version.setId(versionId); version.setShujuLeixing(type);
|
fieldVersions.put(versionId, version);
|
}
|
}
|
|
@Override public List<ElnTemplateFormulaBindingEntity> listFormulaBindings(
|
String tenantId, String templateId) { return Collections.singletonList(formulaBinding); }
|
@Override public ElnTemplateBindingEntity findFieldBinding(String tenantId, String id) { return fields.get(id); }
|
@Override public List<ElnTemplateBindingEntity> listFieldBindings(
|
String tenantId, String templateId) {
|
List<ElnTemplateBindingEntity> result = new java.util.ArrayList<>();
|
for (ElnTemplateBindingEntity field : fields.values())
|
if (templateId.equals(field.getMubanId())) result.add(field);
|
return result;
|
}
|
@Override public ElnFieldVersionEntity findFieldVersion(String tenantId, String id) { return fieldVersions.get(id); }
|
@Override public ElnFormulaVersionEntity findFormulaVersion(String tenantId, String id) {
|
return formulaVersion.getId().equals(id) ? formulaVersion : null;
|
}
|
@Override public ElnFormulaDefEntity findFormulaDefinition(String tenantId, String id) { return definition; }
|
@Override public List<ElnFormulaParameterSlotEntity> listSlots(String tenantId, String versionId) { return Collections.singletonList(slot); }
|
}
|
}
|