From bd942a47477aa5e55da3b8b8c20a71bf61f6b05c Mon Sep 17 00:00:00 2001 From: Jonas Blatt <jonasblatt@uni-koblenz.de> Date: Sat, 12 Oct 2019 19:37:29 +0200 Subject: [PATCH] Add missing input column verifier --- .../result/VerificationResultEntry.java | 46 ++++++------- .../VerificationResultEntryElement.java | 16 +++++ .../verification/result/actions/Action.java | 3 + .../result/actions/ActionScope.java | 1 + .../result/actions/VerificationFix.java | 15 +++-- .../impl/MissingInputColumnVerifier.java | 65 +++++++++++++++++++ 6 files changed, 119 insertions(+), 27 deletions(-) diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/result/VerificationResultEntry.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/result/VerificationResultEntry.java index 2bcaf610..279c2d53 100644 --- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/result/VerificationResultEntry.java +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/result/VerificationResultEntry.java @@ -21,27 +21,7 @@ import org.apache.commons.lang3.Validate; */ public class VerificationResultEntry extends AbstractResultObject { - /** - * Enum to classify one {@link VerificationResultEntry}. - */ - public enum VerificationClassification { - /** - * Only information. - */ - INFO, - /** - * Warning. No action needed. - */ - WARNING, - /** - * Error. Action needed. - */ - ERROR, - /** - * Fatal error. Must be fixed, so that the dmn is executable. - */ - FATAL_ERROR - } + private List<VerificationFix> verificationFixes; /** * Get the list of {@link VerificationFix}es. @@ -52,8 +32,6 @@ public class VerificationResultEntry extends AbstractResultObject { public List<VerificationFix> getVerificationsFixes() { return Collections.unmodifiableList(verificationFixes); } - - private List<VerificationFix> verificationFixes; private Set<VerificationResultEntryElement> verificationResultEntryElements; private Message message; private VerificationClassification verificationClassification; @@ -73,6 +51,28 @@ public class VerificationResultEntry extends AbstractResultObject { return verificationResultEntryElements.size(); } + /** + * Enum to classify one {@link VerificationResultEntry}. + */ + public enum VerificationClassification { + /** + * Only information. + */ + INFO, + /** + * Warning. No action needed. + */ + WARNING, + /** + * Error. Action needed. + */ + ERROR, + /** + * Fatal error. Must be fixed, so that the dmn is executable. + */ + FATAL_ERROR + } + /** * Get the set of {@link VerificationResultEntryElement}s. * diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/result/VerificationResultEntryElement.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/result/VerificationResultEntryElement.java index 9fc64878..cc2584f7 100644 --- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/result/VerificationResultEntryElement.java +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/result/VerificationResultEntryElement.java @@ -3,8 +3,10 @@ package de.unikoblenz.fgbks.core.dmn.verification.result; import de.unikoblenz.fgbks.core.dmn.domain.ids.AbstractId; import de.unikoblenz.fgbks.core.dmn.domain.ids.JsonIdentifier; import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnColumn; +import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnDecision; import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnDecisionTable; import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnInputData; +import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnNode; import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnValue; import java.util.HashMap; import java.util.Map; @@ -97,6 +99,20 @@ public class VerificationResultEntryElement extends AbstractResultObject { .withIdentifier(inputData.getInputDataId()); } + /** + * Create a new {@link VerificationResultEntryElement} with the initial identifier from a {@link + * VDmnNode}. Call {@link VerificationResultEntryElement#withIdentifier(AbstractId)} to add + * further identifier. + * + * @param vDmnNode the {@link VDmnInputData} or {@link VDmnDecision} node + * @return the new {@link VerificationResultEntryElement} + */ + public static VerificationResultEntryElement create(VDmnNode vDmnNode) { + return new VerificationResultEntryElement() + .withIdentifier(vDmnNode.getDmnDefinition().getDefinitionId()) + .withIdentifier(vDmnNode.getId()); + } + /** * Get all required ids ({@link AbstractId}) of the {@link VerificationResultEntryElement}. * diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/result/actions/Action.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/result/actions/Action.java index 9586c99a..44313e92 100644 --- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/result/actions/Action.java +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/result/actions/Action.java @@ -1,5 +1,6 @@ package de.unikoblenz.fgbks.core.dmn.verification.result.actions; +import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionScope.DECISION; import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionScope.INPUT_COLUMN; import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionScope.INPUT_DATA; import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionScope.INPUT_ENTRY; @@ -17,6 +18,7 @@ import org.apache.commons.lang3.Validate; public class Action extends AbstractResultObject { public static Action ACTION_SHOW_INPUT_DATA; + public static Action ACTION_SHOW_DECISION; public static Action ACTION_SHOW_RULES; public static Action ACTION_SHOW_INPUT_ENTRIES; public static Action ACTION_SHOW_OUTPUT_ENTRIES; @@ -25,6 +27,7 @@ public class Action extends AbstractResultObject { static { ACTION_SHOW_INPUT_DATA = getBuilder().withActionType(SHOW).withActionScope(INPUT_DATA).build(); + ACTION_SHOW_DECISION = getBuilder().withActionType(SHOW).withActionScope(DECISION).build(); ACTION_SHOW_RULES = getBuilder().withActionType(SHOW).withActionScope(RULE).build(); ACTION_SHOW_INPUT_ENTRIES = getBuilder().withActionType(SHOW).withActionScope(INPUT_ENTRY).build(); diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/result/actions/ActionScope.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/result/actions/ActionScope.java index 2a529ed1..132d2e91 100644 --- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/result/actions/ActionScope.java +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/result/actions/ActionScope.java @@ -7,5 +7,6 @@ public enum ActionScope { INPUT_DATA, INPUT_COLUMN, OUTPUT_COLUMN, + DECISION_TABLE, DECISION } diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/result/actions/VerificationFix.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/result/actions/VerificationFix.java index a0430635..79f0f6f2 100644 --- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/result/actions/VerificationFix.java +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/result/actions/VerificationFix.java @@ -1,5 +1,6 @@ package de.unikoblenz.fgbks.core.dmn.verification.result.actions; +import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.Action.ACTION_SHOW_DECISION; import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.Action.ACTION_SHOW_INPUT_COLUMNS; import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.Action.ACTION_SHOW_INPUT_DATA; import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.Action.ACTION_SHOW_INPUT_ENTRIES; @@ -15,10 +16,11 @@ import org.apache.commons.lang3.Validate; public class VerificationFix { - private static final Name DEFAULT_FIX_NAME = new Name("Fix"); - private static final Name DEFAULT_SHOW_NAME = new Name("Show"); + public static final Name DEFAULT_FIX_NAME = new Name("Fix"); + public static final Name DEFAULT_SHOW_NAME = new Name("Show"); public static VerificationFix SHOW_INPUT_DATA; + public static VerificationFix SHOW_DECISION; public static VerificationFix SHOW_RULES; public static VerificationFix SHOW_INPUT_ENTRIES; public static VerificationFix SHOW_OUTPUT_ENTRIES; @@ -31,6 +33,11 @@ public class VerificationFix { .withFixName(DEFAULT_SHOW_NAME) .addAction(ACTION_SHOW_INPUT_DATA) .build(); + SHOW_DECISION = + VerificationFix.getBuilder() + .withFixName(DEFAULT_SHOW_NAME) + .addAction(ACTION_SHOW_DECISION) + .build(); SHOW_RULES = VerificationFix.getBuilder() .withFixName(DEFAULT_SHOW_NAME) @@ -66,11 +73,11 @@ public class VerificationFix { actions = new ArrayList<>(); } - private static Builder getBuilder() { + public static Builder getBuilder() { return new VerificationFix().new Builder(); } - private class Builder extends DefaultBuilder<VerificationFix> { + public class Builder extends DefaultBuilder<VerificationFix> { public Builder withFixName(Name fixName) { value.fixName = fixName; diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/MissingInputColumnVerifier.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/MissingInputColumnVerifier.java index c24cc095..803c7255 100644 --- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/MissingInputColumnVerifier.java +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/MissingInputColumnVerifier.java @@ -1,13 +1,78 @@ package de.unikoblenz.fgbks.core.dmn.verification.verifier.impl; +import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.Action.ACTION_SHOW_DECISION; +import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.Action.ACTION_SHOW_INPUT_DATA; +import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.VerificationFix.DEFAULT_SHOW_NAME; + +import de.unikoblenz.fgbks.base.domain.Name; +import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnDecision; +import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnInputData; +import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnNode; +import de.unikoblenz.fgbks.core.dmn.verification.result.VerificationResultEntry.VerificationClassification; +import de.unikoblenz.fgbks.core.dmn.verification.result.VerificationResultEntryElement; +import de.unikoblenz.fgbks.core.dmn.verification.result.actions.VerificationFix; import de.unikoblenz.fgbks.core.dmn.verification.verifier.AbstractVerifier; import de.unikoblenz.fgbks.core.dmn.verification.verifier.DmnVerifier; import de.unikoblenz.fgbks.core.dmn.verification.verifier.types.MissingInputColumnVerification; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; @DmnVerifier(verifierType = MissingInputColumnVerification.class) public class MissingInputColumnVerifier extends AbstractVerifier { + private Name defaultName = new Name("[no name]"); + @Override protected void doVerification() { + // 1. check for input data nodes + for (VDmnInputData inputData : dmnObjectContainer.getVDmnDefinition().getDmnInputData()) { + if (inputData.getName().isPresent()) { + List<Name> inputDataNames = Collections.singletonList(inputData.getName().get()); + checkInputData(inputData, inputDataNames); + } + } + // 2. check for decision nodes + for (VDmnDecision decision : dmnObjectContainer.getVDmnDefinition().getDmnDecisions()) { + List<Name> inputDataNames = + decision.getDmnDecisionTable().getOutputColumns().stream() + .map(c -> c.getName().orElse(null)) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + checkInputData(decision, inputDataNames); + } + } + + private void checkInputData(VDmnNode inputDataNode, List<Name> inputDataNames) { + // Get all outgoing decisions from the current input node + outer: + for (VDmnDecision decision : inputDataNode.getInformationProvidingDecisions()) { + // Check all input columns of the decision node + List<Name> inputColumnsNames = + decision.getDmnDecisionTable().getInputColumns().stream() + .map(x -> x.getName().orElse(null)) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + for (Name inDataName : inputDataNames) { + if (inputColumnsNames.contains(inDataName)) { + continue outer; + } + } + vreFactory + .addElement(VerificationResultEntryElement.create(inputDataNode)) + .addElement(VerificationResultEntryElement.create(decision)) + .addVerificationFix( + VerificationFix.getBuilder() + .withFixName(DEFAULT_SHOW_NAME) + .addAction(ACTION_SHOW_INPUT_DATA) + .addAction(ACTION_SHOW_DECISION) + .build()) + .addToEntry( + VerificationClassification.WARNING, + "Node \"%s\" has no corresponding input column in decision \"%s\"", + inputDataNode.getName().orElse(defaultName), + decision.getName().orElse(defaultName)); + } } } -- GitLab