From 932bc7883b9c836f35b28cf467472a6f2a218537 Mon Sep 17 00:00:00 2001 From: Jonas Blatt <jonasblatt@uni-koblenz.de> Date: Sat, 26 Oct 2019 14:26:34 +0200 Subject: [PATCH] #6 Create verifier for Missing Input Verification --- .../impl/MissingInputValueVerifier.java | 74 ++++++++++++++++++- .../resources/js/dmnVerifierActions.js | 4 +- .../META-INF/resources/js/dmnViewer.js | 34 +++++---- 3 files changed, 96 insertions(+), 16 deletions(-) diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/MissingInputValueVerifier.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/MissingInputValueVerifier.java index 32544d24..c879d4d3 100644 --- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/MissingInputValueVerifier.java +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/MissingInputValueVerifier.java @@ -1,5 +1,21 @@ package de.unikoblenz.fgbks.core.dmn.verification.verifier.impl; +import static de.unikoblenz.fgbks.core.dmn.domain.vdmn.utils.VDmnFunctions.getColumnStringName; +import static de.unikoblenz.fgbks.core.dmn.domain.vdmn.utils.VDmnFunctions.templateDecision; +import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.VerificationFix.DEFAULT_SHOW_NAME; + +import de.unikoblenz.fgbks.base.utils.boundary.Boundary; +import de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType; +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.VDmnInputValue; +import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnOutputColumn; +import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnOutputValue; +import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VTypeRef; +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.Action; +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.MissingInputValueVerification; @@ -9,6 +25,62 @@ public class MissingInputValueVerifier extends AbstractVerifier { @Override protected void doVerification() { - // TODO + for (VDmnDecision decision : dmnObjectContainer.getVDmnDefinition().getDmnDecisions()) { + for (VDmnDecision nextDecision : decision.getInformationProvidingDecisions()) { + checkMissingInputValues(decision, nextDecision); + } + } + } + + private void checkMissingInputValues(VDmnDecision decision, VDmnDecision nextDecision) { + // find the matching output -> input column + for (VDmnOutputColumn outputColumn : decision.getDmnDecisionTable().getOutputColumns()) { + for (VDmnInputColumn inputColumn : nextDecision.getDmnDecisionTable().getInputColumns()) { + if (outputColumn.getName().isPresent() + && inputColumn.getName().isPresent() + && outputColumn.getName().get().equals(inputColumn.getName().get()) + && outputColumn.getTypeRef().equals(inputColumn.getTypeRef())) { + checkMissingInputValues(outputColumn, inputColumn); + } + } + } + } + + private void checkMissingInputValues(VDmnOutputColumn outputColumn, VDmnInputColumn inputColumn) { + // check for each value on outputColumn, if it is used in the inputColumn + outer: + for (VDmnOutputValue outputValue : outputColumn.getDmnOutputValues()) { + if (!outputValue.getText().getValue().isEmpty()) { + // create pseudo boundary for output value + String outputText = outputValue.getText().getValue(); + if (outputColumn.getTypeRef() == VTypeRef.DOUBLE + || outputColumn.getTypeRef() == VTypeRef.INTEGER + || outputColumn.getTypeRef() == VTypeRef.LONG) { + outputText = "= " + outputText; + } + Boundary b = outputColumn.getTypeRef().getBoundaryFromText(outputText); + for (VDmnInputValue inputValue : inputColumn.getInputValues()) { + if (b.checkWith(BoundaryCheckType.IS_IN_CONTACT, inputValue.getBoundary())) { + continue outer; + } + } + // no matching input value found for current output Value + vreFactory + .addElement(VerificationResultEntryElement.create(inputColumn)) + .addElement(VerificationResultEntryElement.create(outputValue)) + .addVerificationFix( + VerificationFix.getBuilder() + .withFixName(DEFAULT_SHOW_NAME) + .addAction(Action.ACTION_SHOW_OUTPUT_ENTRIES) + .addAction(Action.ACTION_SHOW_INPUT_COLUMNS) + .build()) + .addToEntry( + VerificationClassification.WARNING, + templateDecision(inputColumn.getDmnDecision()) + + "Input column \"%s\" never handles the value '%s'.", + getColumnStringName(inputColumn), + outputValue.getText().getValue()); + } + } } } diff --git a/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnVerifierActions.js b/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnVerifierActions.js index 75706537..a0ad8640 100644 --- a/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnVerifierActions.js +++ b/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnVerifierActions.js @@ -124,7 +124,7 @@ function fixSHOW_OUTPUT_COLUMN(verificationEntry, fixAction) { * @param {Action} fixAction */ function fixSHOW_DECISION_TABLE(verificationEntry, fixAction) { - highlightDecision(verificationEntry.elements); + highlightDecisions(verificationEntry.elements); } /** @@ -133,5 +133,5 @@ function fixSHOW_DECISION_TABLE(verificationEntry, fixAction) { * @param {Action} fixAction */ function fixSHOW_DECISION(verificationEntry, fixAction) { - highlightDecision(verificationEntry.elements); + highlightDecisions(verificationEntry.elements); } diff --git a/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnViewer.js b/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnViewer.js index b40ca4a6..7ab3c8d3 100644 --- a/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnViewer.js +++ b/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnViewer.js @@ -131,6 +131,12 @@ function cleanHighlightFunction() { renderHighlightFunction = []; } +function highlightMultipleDecisions(elements) { + elements.forEach(function (el) { + highlightSingleDecision(el.identifier['decisionId']); + }); +} + function highlightSingleDecision(decisionId) { // node let $decisionNode = $( @@ -140,6 +146,12 @@ function highlightSingleDecision(decisionId) { $('#tab-dec-' + decisionId).addClass('highlight'); } +function cleanMultipleDecisions(elements) { + elements.forEach(function (el) { + cleanSingleDecision(el.identifier['decisionId']); + }); +} + function cleanSingleDecision(decisionId) { // node let $decisionNode = $( @@ -156,14 +168,14 @@ function cleanSingleDecision(decisionId) { function highlightRules(elements) { renderHighlightFunction.push({ highlight: function () { - highlightSingleDecision(elements[0].identifier['decisionId']); + highlightMultipleDecisions(elements); elements.forEach(function (el) { $('[data-row-id=' + el.identifier['ruleId'] + ']').addClass( 'highlight'); }); }, clean: function () { - cleanSingleDecision(elements[0].identifier['decisionId']); + cleanMultipleDecisions(elements); elements.forEach(function (el) { $('[data-row-id=' + el.identifier['ruleId'] + ']').removeClass( 'highlight'); @@ -180,14 +192,14 @@ function highlightRules(elements) { function highlightColumns(elements, identifier) { renderHighlightFunction.push({ highlight: function () { - highlightSingleDecision(elements[0].identifier['decisionId']); + highlightMultipleDecisions(elements); elements.forEach(function (el) { $('[data-col-id=' + el.identifier[identifier] + ']').addClass( 'highlight'); }); }, clean: function () { - cleanSingleDecision(elements[0].identifier['decisionId']); + cleanMultipleDecisions(elements); elements.forEach(function (el) { $('[data-col-id=' + el.identifier[identifier] + ']').removeClass( 'highlight'); @@ -204,14 +216,14 @@ function highlightColumns(elements, identifier) { function highlightDataEntries(elements, identifier) { renderHighlightFunction.push({ highlight: function () { - highlightSingleDecision(elements[0].identifier['decisionId']); + highlightMultipleDecisions(elements); elements.forEach(function (el) { $('[data-element-id=' + el.identifier[identifier] + ']').addClass( 'highlight'); }); }, clean: function () { - cleanSingleDecision(elements[0].identifier['decisionId']); + cleanMultipleDecisions(elements); elements.forEach(function (el) { $('[data-element-id=' + el.identifier[identifier] + ']').removeClass( 'highlight'); @@ -245,18 +257,14 @@ function highlightInputData(elements) { * * @param {Array<VerificationEntryElement>}elements */ -function highlightDecision(elements) { +function highlightDecisions(elements) { console.log(elements); renderHighlightFunction.push({ highlight: function () { - elements.forEach(function (el) { - highlightSingleDecision(el.identifier['decisionId']); - }); + highlightMultipleDecisions(elements) }, clean: function () { - elements.forEach(function (el) { - cleanSingleDecision(el.identifier['decisionId']); - }); + cleanMultipleDecisions(elements); } }); } -- GitLab