From dcf9dba4758cff2d40d499a13e9657c2bcb730a3 Mon Sep 17 00:00:00 2001 From: Jonas Blatt <jonasblatt@uni-koblenz.de> Date: Sun, 13 Oct 2019 08:48:27 +0200 Subject: [PATCH] Feat/verifier --- dmnverifierapi/README.md | 3 + .../base/json/PrivateVisibilityStrategy.java | 3 +- .../fgbks/core/dmn/domain/vdmn/VDmnNode.java | 18 ++ .../result/VerificationResultEntry.java | 64 +++--- .../VerificationResultEntryElement.java | 31 +++ .../verification/result/actions/Action.java | 6 + .../result/actions/ActionScope.java | 6 +- .../result/actions/VerificationFix.java | 33 ++- .../verifier/AbstractVerifier.java | 16 +- .../DrdModelingLevelVerification.java | 19 ++ .../impl/LonelyDataInputVerifier.java | 32 +++ .../impl/MissingInputColumnVerifier.java | 78 +++++++ .../impl/MissingInputDataVerifier.java | 71 ++++++ .../types/EmptyOutputVerification.java | 4 +- .../types/LonelyDataInputVerification.java | 29 +++ .../types/MissingInputColumnVerification.java | 30 +++ .../types/MissingInputDataVerification.java | 30 +++ dmnverifierapi/verifier.md | 203 ++++++++++++++++++ 18 files changed, 625 insertions(+), 51 deletions(-) create mode 100644 dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/classification/DrdModelingLevelVerification.java create mode 100644 dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/LonelyDataInputVerifier.java create mode 100644 dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/MissingInputColumnVerifier.java create mode 100644 dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/MissingInputDataVerifier.java create mode 100644 dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/LonelyDataInputVerification.java create mode 100644 dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/MissingInputColumnVerification.java create mode 100644 dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/MissingInputDataVerification.java create mode 100644 dmnverifierapi/verifier.md diff --git a/dmnverifierapi/README.md b/dmnverifierapi/README.md index 0f91a6df..85520266 100644 --- a/dmnverifierapi/README.md +++ b/dmnverifierapi/README.md @@ -12,3 +12,6 @@ This project contains all source files of the implementation, created for the ma Based on - [Quarkus](https://quarkus.io/) - [Camunda DMN](https://github.com/camunda/camunda-dmn-model/) + +## Verifier +- [Overview verifier](verifier.md) diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/json/PrivateVisibilityStrategy.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/json/PrivateVisibilityStrategy.java index 8ab6492b..d3c08ce2 100644 --- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/json/PrivateVisibilityStrategy.java +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/json/PrivateVisibilityStrategy.java @@ -15,7 +15,8 @@ public class PrivateVisibilityStrategy implements PropertyVisibilityStrategy { @Override public boolean isVisible(Field field) { - return !field.isAnnotationPresent(JsonbTransient.class); + return !field.isAnnotationPresent(JsonbTransient.class) + && Modifier.isPublic(field.getModifiers()); } @Override diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/domain/vdmn/VDmnNode.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/domain/vdmn/VDmnNode.java index e1be6f7a..d93f22cf 100644 --- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/domain/vdmn/VDmnNode.java +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/domain/vdmn/VDmnNode.java @@ -31,4 +31,22 @@ public interface VDmnNode extends VDmnElement { * @return an optional {@link Name} */ Optional<Name> getName(); + + /** + * Check, if the node is a {@link VDmnDecision} node. + * + * @return true, if the node is a {@link VDmnDecision} + */ + default boolean isDecision() { + return this instanceof VDmnDecision; + } + + /** + * Check, if the node is a {@link VDmnInputData} node. + * + * @return true, if the node is a {@link VDmnInputData} + */ + default boolean isInputData() { + return this instanceof VDmnInputData; + } } 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..00f31cc6 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,26 +21,14 @@ 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; + private Set<VerificationResultEntryElement> verificationResultEntryElements; + private Message message; + private VerificationClassification verificationClassification; + + protected VerificationResultEntry() { + this.verificationResultEntryElements = ConcurrentHashMap.newKeySet(); + verificationFixes = new ArrayList<>(); } /** @@ -53,16 +41,6 @@ public class VerificationResultEntry extends AbstractResultObject { return Collections.unmodifiableList(verificationFixes); } - private List<VerificationFix> verificationFixes; - private Set<VerificationResultEntryElement> verificationResultEntryElements; - private Message message; - private VerificationClassification verificationClassification; - - protected VerificationResultEntry() { - this.verificationResultEntryElements = ConcurrentHashMap.newKeySet(); - verificationFixes = new ArrayList<>(); - } - /** * Get the amount of verification result entry elements. * @@ -73,6 +51,16 @@ public class VerificationResultEntry extends AbstractResultObject { return verificationResultEntryElements.size(); } + /** + * Get the {@link VerificationClassification}. + * + * @return the {@link VerificationClassification} + */ + @JsonbProperty("verificationClassifications") + public VerificationClassification getVerificationClassification() { + return verificationClassification; + } + /** * Get the set of {@link VerificationResultEntryElement}s. * @@ -84,13 +72,17 @@ public class VerificationResultEntry extends AbstractResultObject { } /** - * Get the {@link VerificationClassification}. - * - * @return the {@link VerificationClassification} + * Enum to classify one {@link VerificationResultEntry}. */ - @JsonbProperty("verificationClassification") - public VerificationClassification getVerificationClassification() { - return verificationClassification; + 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 } /** 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 d25bbe50..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,7 +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; @@ -82,6 +85,34 @@ public class VerificationResultEntryElement extends AbstractResultObject { .withIdentifier(column.getColumnId()); } + /** + * Create a new {@link VerificationResultEntryElement} with the initial identifier from a {@link + * VDmnInputData}. Call {@link VerificationResultEntryElement#withIdentifier(AbstractId)} to add + * further identifier. + * + * @param inputData the {@link VDmnInputData} + * @return the new {@link VerificationResultEntryElement} + */ + public static VerificationResultEntryElement create(VDmnInputData inputData) { + return new VerificationResultEntryElement() + .withIdentifier(inputData.getDmnDefinition().getDefinitionId()) + .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 43d77979..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,6 +1,8 @@ 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; import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionScope.OUTPUT_COLUMN; import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionScope.OUTPUT_ENTRY; @@ -15,6 +17,8 @@ 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; @@ -22,6 +26,8 @@ public class Action extends AbstractResultObject { public static Action ACTION_SHOW_OUTPUT_COLUMNS; 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 5988bfa9..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 @@ -4,7 +4,9 @@ public enum ActionScope { RULE, INPUT_ENTRY, OUTPUT_ENTRY, - INPUT_NODE, + INPUT_DATA, INPUT_COLUMN, - OUTPUT_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 32f837e0..32ffe592 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,11 +1,14 @@ 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; import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.Action.ACTION_SHOW_OUTPUT_COLUMNS; import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.Action.ACTION_SHOW_OUTPUT_ENTRIES; import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.Action.ACTION_SHOW_RULES; +import com.fasterxml.jackson.annotation.JsonProperty; import de.unikoblenz.fgbks.base.builder.DefaultBuilder; import de.unikoblenz.fgbks.base.domain.Name; import java.util.ArrayList; @@ -14,9 +17,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; @@ -24,6 +29,16 @@ public class VerificationFix { public static VerificationFix SHOW_OUTPUT_COLUMNS; static { + SHOW_INPUT_DATA = + VerificationFix.getBuilder() + .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) @@ -54,16 +69,26 @@ public class VerificationFix { private Name fixName; private List<Action> actions; + @JsonProperty("fixName") + public Name getFixName() { + return fixName; + } + + @JsonProperty("actions") + public List<Action> getActions() { + return actions; + } + private VerificationFix() { fixName = DEFAULT_FIX_NAME; 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/AbstractVerifier.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/AbstractVerifier.java index 0d02dbb5..21aa38ce 100644 --- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/AbstractVerifier.java +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/AbstractVerifier.java @@ -27,14 +27,16 @@ public abstract class AbstractVerifier implements Verifier { protected VerificationType verificationType; protected AbstractDmnVerifierConfig verifierConfig; protected VerifierResult.Builder resultBuilder; + /** + * The {@link VerificationResultEntryFactory} for adding result entries. + */ protected VerificationResultEntryFactory vreFactory; + protected DmnObjectContainer dmnObjectContainer; private long executionTime = -1; - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ @Override public VerificationType getVerificationType() { return verificationType; @@ -94,14 +96,16 @@ public abstract class AbstractVerifier implements Verifier { + " finished. Id: " + this.verifierConfig.getVerificationProcessId() + " Time Elapsed: " - + +executionTime - + " nano seconds"); + + executionTime + + " nano seconds; Or " + + executionTime / 1000000 + + " ms"); return resultBuilder.withExecutionTime(executionTime).build(); } /** * This method must be implemented by the finial verifiers and should contain the calculation of - * the verifier. + * the verifier. The {@link AbstractVerifier#vreFactory} can be used for adding result entries. */ protected abstract void doVerification(); diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/classification/DrdModelingLevelVerification.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/classification/DrdModelingLevelVerification.java new file mode 100644 index 00000000..6de26519 --- /dev/null +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/classification/DrdModelingLevelVerification.java @@ -0,0 +1,19 @@ +package de.unikoblenz.fgbks.core.dmn.verification.verifier.classification; + +import de.unikoblenz.fgbks.base.domain.Description; +import de.unikoblenz.fgbks.base.domain.Name; + +@Classification +public class DrdModelingLevelVerification extends AbstractClassificationType { + + private static final DrdModelingLevelVerification instance = + new DrdModelingLevelVerification(); + + private DrdModelingLevelVerification() { + super(new Name("DrdModeling"), new Description("test")); // TODO + } + + public static DrdModelingLevelVerification getInstance() { + return instance; + } +} diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/LonelyDataInputVerifier.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/LonelyDataInputVerifier.java new file mode 100644 index 00000000..7fd25b44 --- /dev/null +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/LonelyDataInputVerifier.java @@ -0,0 +1,32 @@ +package de.unikoblenz.fgbks.core.dmn.verification.verifier.impl; + +import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.VerificationFix.SHOW_INPUT_DATA; + +import de.unikoblenz.fgbks.base.domain.Name; +import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnInputData; +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.verifier.AbstractVerifier; +import de.unikoblenz.fgbks.core.dmn.verification.verifier.DmnVerifier; +import de.unikoblenz.fgbks.core.dmn.verification.verifier.types.LonelyDataInputVerification; + +@DmnVerifier(verifierType = LonelyDataInputVerification.class) +public class LonelyDataInputVerifier extends AbstractVerifier { + + private Name defaultName = new Name("[no name]"); + + @Override + protected void doVerification() { + for (VDmnInputData i : dmnObjectContainer.getVDmnDefinition().getDmnInputData()) { + if (i.getInformationProvidingDecisions().isEmpty()) { + vreFactory + .addElement(VerificationResultEntryElement.create(i)) + .addVerificationFix(SHOW_INPUT_DATA) + .addToEntry( + VerificationClassification.WARNING, + "Input data \"%s\" has no outgoing connections to at least one decision node.", + i.getName().orElse(defaultName)); + } + } + } +} 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 new file mode 100644 index 00000000..803c7255 --- /dev/null +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/MissingInputColumnVerifier.java @@ -0,0 +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)); + } + } +} diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/MissingInputDataVerifier.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/MissingInputDataVerifier.java new file mode 100644 index 00000000..d498c3e3 --- /dev/null +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/MissingInputDataVerifier.java @@ -0,0 +1,71 @@ +package de.unikoblenz.fgbks.core.dmn.verification.verifier.impl; + +import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.VerificationFix.SHOW_INPUT_COLUMNS; + +import de.unikoblenz.fgbks.base.domain.Name; +import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnDecision; +import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnInputColumn; +import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnNode; +import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnOutputColumn; +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.verifier.AbstractVerifier; +import de.unikoblenz.fgbks.core.dmn.verification.verifier.DmnVerifier; +import de.unikoblenz.fgbks.core.dmn.verification.verifier.types.MissingInputDataVerification; +import java.util.List; + +@DmnVerifier(verifierType = MissingInputDataVerification.class) +public class MissingInputDataVerifier extends AbstractVerifier { + + @Override + protected void doVerification() { + for (VDmnDecision decision : dmnObjectContainer.getVDmnDefinition().getDmnDecisions()) { + List<VDmnNode> inputNodes = decision.getDmnInformationRequirements(); + // Check for each input column if there is one input data node or one output column from a + // decision node + for (VDmnInputColumn inputColumn : decision.getDmnDecisionTable().getInputColumns()) { + checkExistingInputData(inputColumn, inputNodes); + } + } + } + + private void checkExistingInputData(VDmnInputColumn inputColumn, List<VDmnNode> inputNodes) { + // if the inputColumn has no name, add the column + if (inputColumn.getName().isPresent()) { + Name inputColumnName = inputColumn.getName().get(); + // check, if there is one input Data with the same name + for (VDmnNode node : inputNodes) { + // input Data node, check only the name + if (node.isInputData()) { + if (node.getName().isPresent() && node.getName().get().equals(inputColumnName)) { + return; + } + } else if (node.isDecision()) { + VDmnDecision decision = (VDmnDecision) node; + // check for each output column, if the name of the output column matches the input column + // name + for (VDmnOutputColumn outputColumn : decision.getDmnDecisionTable().getOutputColumns()) { + if (outputColumn.getName().isPresent() + && outputColumn.getName().get().equals(inputColumnName)) { + return; + } + } + } + } + } + // no input data found yet -> add column to results + String label = ""; + if (inputColumn.getLabel().isPresent()) { + label = inputColumn.getLabel().get().getValue(); + } else if (inputColumn.getName().isPresent()) { + label = inputColumn.getName().get().getValue(); + } else { + label = "no name"; + } + vreFactory + .addElement(VerificationResultEntryElement.create(inputColumn)) + .addVerificationFix(SHOW_INPUT_COLUMNS) + .addToEntry( + VerificationClassification.WARNING, "Input column \"%s\" has no input data.", label); + } +} diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/EmptyOutputVerification.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/EmptyOutputVerification.java index b90a710d..5c7c7a14 100644 --- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/EmptyOutputVerification.java +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/EmptyOutputVerification.java @@ -3,7 +3,7 @@ package de.unikoblenz.fgbks.core.dmn.verification.verifier.types; import de.unikoblenz.fgbks.base.domain.Description; import de.unikoblenz.fgbks.base.domain.Name; import de.unikoblenz.fgbks.core.dmn.verification.verifier.classification.ClassificationType; -import de.unikoblenz.fgbks.core.dmn.verification.verifier.classification.SyntaxLevelVerification; +import de.unikoblenz.fgbks.core.dmn.verification.verifier.classification.ModelingLevelVerification; import javax.validation.constraints.NotNull; @Type @@ -21,6 +21,6 @@ public class EmptyOutputVerification extends AbstractVerificationType { @Override public @NotNull ClassificationType getClassification() { - return SyntaxLevelVerification.getInstance(); + return ModelingLevelVerification.getInstance(); } } diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/LonelyDataInputVerification.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/LonelyDataInputVerification.java new file mode 100644 index 00000000..201bfa5a --- /dev/null +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/LonelyDataInputVerification.java @@ -0,0 +1,29 @@ +package de.unikoblenz.fgbks.core.dmn.verification.verifier.types; + +import de.unikoblenz.fgbks.base.domain.Description; +import de.unikoblenz.fgbks.base.domain.Name; +import de.unikoblenz.fgbks.core.dmn.verification.verifier.classification.ClassificationType; +import de.unikoblenz.fgbks.core.dmn.verification.verifier.classification.DrdModelingLevelVerification; +import javax.validation.constraints.NotNull; + +@Type +public class LonelyDataInputVerification extends AbstractVerificationType { + + private static final LonelyDataInputVerification instance = new LonelyDataInputVerification(); + + private LonelyDataInputVerification() { + super( + new Name("LonelyDataInputVerification"), + new Description( + "Checks for any input data node, if it has no connection to at least one decision table.")); + } + + public static LonelyDataInputVerification getInstance() { + return instance; + } + + @Override + public @NotNull ClassificationType getClassification() { + return DrdModelingLevelVerification.getInstance(); + } +} diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/MissingInputColumnVerification.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/MissingInputColumnVerification.java new file mode 100644 index 00000000..01a42585 --- /dev/null +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/MissingInputColumnVerification.java @@ -0,0 +1,30 @@ +package de.unikoblenz.fgbks.core.dmn.verification.verifier.types; + +import de.unikoblenz.fgbks.base.domain.Description; +import de.unikoblenz.fgbks.base.domain.Name; +import de.unikoblenz.fgbks.core.dmn.verification.verifier.classification.ClassificationType; +import de.unikoblenz.fgbks.core.dmn.verification.verifier.classification.DrdModelingLevelVerification; +import javax.validation.constraints.NotNull; + +@Type +public class MissingInputColumnVerification extends AbstractVerificationType { + + private static final MissingInputColumnVerification instance = + new MissingInputColumnVerification(); + + private MissingInputColumnVerification() { + super( + new Name("MissingInputColumnVerification"), + new Description( + "todo")); // TODO englisch + } + + public static MissingInputColumnVerification getInstance() { + return instance; + } + + @Override + public @NotNull ClassificationType getClassification() { + return DrdModelingLevelVerification.getInstance(); + } +} diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/MissingInputDataVerification.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/MissingInputDataVerification.java new file mode 100644 index 00000000..1aea6303 --- /dev/null +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/MissingInputDataVerification.java @@ -0,0 +1,30 @@ +package de.unikoblenz.fgbks.core.dmn.verification.verifier.types; + +import de.unikoblenz.fgbks.base.domain.Description; +import de.unikoblenz.fgbks.base.domain.Name; +import de.unikoblenz.fgbks.core.dmn.verification.verifier.classification.ClassificationType; +import de.unikoblenz.fgbks.core.dmn.verification.verifier.classification.DrdModelingLevelVerification; +import javax.validation.constraints.NotNull; + +@Type +public class MissingInputDataVerification extends AbstractVerificationType { + + private static final MissingInputDataVerification instance = + new MissingInputDataVerification(); + + private MissingInputDataVerification() { + super( + new Name("MissingInputDataVerification"), + new Description( + "todo")); // TODO englisch + } + + public static MissingInputDataVerification getInstance() { + return instance; + } + + @Override + public @NotNull ClassificationType getClassification() { + return DrdModelingLevelVerification.getInstance(); + } +} diff --git a/dmnverifierapi/verifier.md b/dmnverifierapi/verifier.md new file mode 100644 index 00000000..662a9615 --- /dev/null +++ b/dmnverifierapi/verifier.md @@ -0,0 +1,203 @@ +# Verifier + +## Overview +- [Verification Classification (Group of verifier)](src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/classification) +- [Verification Type (identification of verifier + name + description for single verifier)](src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types) +- [Verifier (Concrete implementation)](src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl) + +## DRD Modeling Level Verification +- Classification: [DrdModelingLevelVerification](src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/classification/DrdModelingLevelVerification.java) + +### Lonely Data Input Verification +- Type: [LonelyDataInputVerification](src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/LonelyDataInputVerification.java) +- Verifier: [LonelyDataInputVerifier](src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/LonelyDataInputVerifier.java) + +#### Description +Checks for any input data node, if it has **no** connection to at least one decision table. + +#### Algorithm +``` +doVerification (Definition d) { + define rL as ResultList + for each (InputNode i in d.getInputNodes()) { + if (i.hasNoConnectedDecisionNodes()) { + add i to rL + } + } + return rL +} +``` + +### Missing Input Data Verification +- Type: [MissingInputDataVerification](src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/MissingInputDataVerification.java) +- Verifier: [MissingInputDataVerifier](src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/MissingInputDataVerifier.java) + +#### Description + +#### Algorithm +``` +TODO +``` + +### Missing Input Column Verification +- Type: [MissingInputColumnVerification](src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/MissingInputColumnVerification.java) +- Verifier: [MissingInputColumnVerifier](src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/MissingInputColumnVerifier.java) + +#### Description + +#### Algorithm +``` +TODO +``` + +## Modeling Level Verification +- Classification: [ModelingLevelVerification](src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/classification/ModelingLevelVerification.java) + +### Predefined Existing Value Verification +- Type: [PredefinedExistingValueVerification](/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/PredefinedExistingValueVerification.java) +- Verifier: [PredefinedExistingValueVerifier](src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/PredefinedExistingValueVerifier.java) + +#### Description +TODO + +#### Algorithm +``` +TODO +``` + +### Predefined Missing Value Verification +- Type: [PredefinedMissingValueVerification](/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/PredefinedMissingValueVerification.java) +- Verifier: [PredefinedMissingValueVerifier](src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/PredefinedMissingValueVerifier.java) + +#### Description +TODO + +#### Algorithm +``` +TODO +``` + +### Empty Output Verification +- Type: [EmptyOutputVerification](/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/EmptyOutputVerification.java) +- Verifier: [EmptyOutputVerifier](src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/EmptyOutputVerifier.java) + +#### Description +This verification checks if a output entry is empty. + +#### Algorithm +``` +TODO +``` + +## Decision Logic Level Verification +- Classification: [DecisionLogicLevelVerification](src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/classification/DecisionLogicLevelVerification.java) + +### Subsumption Verification +- Type: [SubsumptionVerification](/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/SubsumptionVerification.java) +- Verifier: [SubsumptionVerifier](src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/SubsumptionVerifier.java) + +#### Description +TODO + +#### Algorithm +``` +TODO +``` + +### Partial Reduction Verification +- Type: [PartialReductionVerification](/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/PartialReductionVerification.java) +- Verifier: [PartialReductionVerifier](src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/PartialReductionVerifier.java) + +#### Description +TODO + +#### Algorithm +``` +TODO +``` + +### Overlapping Verification +- Type: [OverlappingVerification](/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/OverlappingVerification.java) +- Verifier: [OverlappingVerifier](src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/OverlappingVerifier.java) + +#### Description +TODO + +#### Algorithm +``` +TODO +``` + +### Missing Rule Verification +- Type: [MissingRuleVerification](/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/MissingRuleVerification.java) +- Verifier: [MissingRuleVerifier](src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/MissingRuleVerifier.java) + +#### Description +TODO + +#### Algorithm +``` +TODO +``` + +### Identical Business Rule Verification +- Type: [IdenticalBusinessRuleVerification](/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/IdenticalBusinessRuleVerification.java) +- Verifier: [IdenticalVerifier](src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/IdenticalVerifier.java) + +#### Description +TODO + +#### Algorithm +``` +TODO +``` + +### Equivalent String Verification +- Type: [EquivalentStringVerification](/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/EquivalentStringVerification.java) +- Verifier: [EquivalentVerifier](src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/EquivalentVerifier.java) + +#### Description +TODO + +#### Algorithm +``` +TODO +``` + +## Syntax Level Verification +- Classification: [SyntaxLevelVerification](src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/classification/SyntaxLevelVerification.java) + +### Date Format Verification +- Type: [DateVerification](/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/DateVerification.java) +- Verifier: [DateVerifier](src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/DateVerifier.java) + +#### Description +This verification checks the correctness of the date format for all date entries. Each date should be in the format "data and time(yyyy-MM-ddThH:mm:ss)". + +#### Algorithm +``` +TODO +``` + +### Input Value Syntax Verification +- Type: [InputValueSyntaxVerification](/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/InputValueSyntaxVerification.java) +- Verifier: [InputValueSyntaxVerifier](src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/InputValueSyntaxVerifier.java) + +#### Description +This verification checks the correctness of the input formats for all input entries. They should have no syntax errors. + +For example: +A numeric input value must have one of the following formats: +- `= x` +- `<= x` +- `> x` +- `>= x` +- `[x..y]` +- `]x..y[` +- `[x..y[` +- `]x..y]` + +#### Algorithm +``` +TODO +``` -- GitLab