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 0843dd0527a9240e5da3dd25ab63f1f598e9d4c3..cbef84a574e1b9c46955b5f0b7b1b7aa69d12db5 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 @@ -8,8 +8,12 @@ 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.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.result.actions.Action; +import de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionScope; +import de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionType; 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; @@ -47,13 +51,13 @@ public class MissingInputColumnVerifier extends AbstractVerifier { outer: for (VDmnDecision decision : inputDataNode.getInformationProvidingDecisions()) { // Check all input columns of the decision node - List<Name> inputColumnsNames = + List<Name> inputColumnNames = decision.getDmnDecisionTable().getInputColumns().stream() .map(x -> x.getName().orElse(null)) .filter(Objects::nonNull) .collect(Collectors.toList()); for (Name inDataName : inputDataNames) { - if (inputColumnsNames.contains(inDataName)) { + if (inputColumnNames.contains(inDataName)) { continue outer; } } @@ -65,13 +69,61 @@ public class MissingInputColumnVerifier extends AbstractVerifier { .withFixName(DEFAULT_SHOW_NAME) .addAction(ACTION_SHOW_INPUT_DATA) .addAction(ACTION_SHOW_DECISION) - .build()) - .addToEntry( - VerificationClassification.WARNING, - (inputDataNode.isInputData() ? "Input data" : "Decision") - + " node \"%s\" has no corresponding input column in decision \"%s\"", - inputDataNode.getName().orElse(Name.NO_NAME), - decision.getName().orElse(Name.NO_NAME)); + .build()); + // Add action remove input data + if (inputDataNode.isInputData()) { + vreFactory.addVerificationFix( + VerificationFix.getBuilder() + .withFixName(new Name("Delete Input Data")) + .addAction( + Action.getBuilder() + .withActionType(ActionType.DELETE) + .withActionScope(ActionScope.INPUT_DATA) + .build()) + .build()); + } + // Add action add input column + if (inputDataNode.isInputData()) { + vreFactory.addVerificationFix( + VerificationFix.getBuilder() + .withFixName( + new Name("Add Input Column " + inputDataNode.getName().get().getValue())) + .addAction( + Action.getBuilder() + .withActionType(ActionType.CREATE) + .withActionScope(ActionScope.INPUT_COLUMN) + .addValue("decisionId", decision.getDecisionId().getValue()) + .addValue("name", inputDataNode.getName().get().getValue()) + .addValue("typeRef", "string") + .build()) + .build()); + } else { + for (VDmnOutputColumn outputColumn : + ((VDmnDecision) inputDataNode).getDmnDecisionTable().getOutputColumns()) { + if (outputColumn.getName().isPresent()) { + vreFactory.addVerificationFix( + VerificationFix.getBuilder() + .withFixName( + new Name("Add Input Column " + outputColumn.getName().get().getValue())) + .addAction( + Action.getBuilder() + .withActionType(ActionType.CREATE) + .withActionScope(ActionScope.INPUT_COLUMN) + .addValue("decisionId", decision.getDecisionId().getValue()) + .addValue("name", outputColumn.getName().get().getValue()) + .addValue("typeRef", outputColumn.getTypeRef().getName()) + .build()) + .build()); + } + } + } + + vreFactory.addToEntry( + VerificationClassification.WARNING, + (inputDataNode.isInputData() ? "Input data" : "Decision") + + " node \"%s\" has no corresponding input column in decision \"%s\"", + inputDataNode.getName().orElse(Name.NO_NAME), + decision.getName().orElse(Name.NO_NAME)); } } } diff --git a/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnVerifier.js b/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnVerifier.js index 6892d48e40833373594954c224321d3b18e4b0c0..e987326f84a7d9288c1e4aa1f838d6fad93d75d9 100644 --- a/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnVerifier.js +++ b/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnVerifier.js @@ -1,5 +1,5 @@ -let rootUrl = 'http://' + window.location.hostname + ':8080/'; -let dmnApi = rootUrl + 'api/dmn/'; +const rootUrl = 'http://' + window.location.hostname + ':8080/'; +const dmnApi = rootUrl + 'api/dmn/'; let inactiveBackend = true; $(document).ready(function () { 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 8c05d667e76dbf1abc8a98ee86144dcf0043d792..05764793f5483b015450bfa2ba778220ae1eb149 100644 --- a/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnVerifierActions.js +++ b/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnVerifierActions.js @@ -9,6 +9,10 @@ function getShapeWithId(id) { return getCurrentModeler()._canvas._elementRegistry.get(id); } +function getSheetElementWithId(id) { + return getCurrentModeler()._sheet._elementRegistry.get(id); +} + /** * * @param {VerificationEntry} verificationEntry @@ -166,9 +170,11 @@ function performVerificationFixCREATE(verificationEntry, fixAction) { case 'INPUT_DATA': createInputData(verificationEntry, fixAction); break; + case 'INPUT_COLUMN': + createInputColumn(verificationEntry, fixAction); + break; case 'INPUT_ENTRY': case 'OUTPUT_ENTRY': - case 'INPUT_COLUMN': case 'OUTPUT_COLUMN': case 'DECISION_TABLE': case 'DECISION': @@ -217,6 +223,21 @@ function createInputData(verificationEntry, fixAction) { openViewWithId(verificationEntry.elements[0].identifier['definitionId']); } +/** + * + * @param {VerificationEntry} verificationEntry + * @param {Action} fixAction + */ +function createInputColumn(verificationEntry, fixAction) { + // getCurrentModeler().createShape(getCurrentModeler()._elementFactory.createDrdElement('shape', {type:'dmn:InputData'}), {x:0,y:0}, dmnModeler._definitions) + openViewWithId(fixAction.actionValues['decisionId']); + const modeler = getCurrentModeler(); + let col = modeler.addCol({type: 'dmn:InputClause'}); + col.businessObject.inputExpression.typeRef = fixAction.actionValues['typeRef'].toLowerCase(); + col.businessObject.inputExpression.text = fixAction.actionValues['name']; + openViewWithId(fixAction.actionValues['decisionId']); +} + /** * * @param {VerificationEntry} verificationEntry @@ -227,11 +248,17 @@ function performVerificationFixDELETE(verificationEntry, fixAction) { case 'RULE': deleteRule(verificationEntry, fixAction); break; - case 'INPUT_ENTRY': - case 'OUTPUT_ENTRY': - case 'INPUT_DATA': case 'INPUT_COLUMN': + deleteColumn(verificationEntry, fixAction, 'inputId'); + break; case 'OUTPUT_COLUMN': + deleteColumn(verificationEntry, fixAction, 'outputId'); + break; + case 'INPUT_DATA': + deleteInputData(verificationEntry, fixAction); + break; + case 'INPUT_ENTRY': + case 'OUTPUT_ENTRY': case 'DECISION_TABLE': case 'DECISION': default: @@ -255,6 +282,39 @@ function deleteRule(verificationEntry, fixAction) { } } +/** + * + * @param {VerificationEntry} verificationEntry + * @param {Action} fixAction + * @param {String} columnIdName + */ +function deleteColumn(verificationEntry, fixAction, columnIdName) { + openViewWithId(verificationEntry.elements[0].identifier['decisionId']); + const modeler = getCurrentModeler(); + verificationEntry.elements.forEach(function (el) { + let col = getSheetElementWithId(el.identifier[columnIdName]); + if (col) { + modeler.removeCol(col); + } + }); +} + +/** + * + * @param {VerificationEntry} verificationEntry + * @param {Action} fixAction + */ +function deleteInputData(verificationEntry, fixAction) { + openViewWithId(verificationEntry.elements[0].identifier['definitionId']); + const modeler = getCurrentModeler(); + verificationEntry.elements.forEach(function (el) { + let inputData = getShapeWithId(el.identifier['inputDataId']); + if (inputData) { + modeler.removeShape(inputData); + } + }); +} + // get a rule: // dmnModeler.getActiveViewer().get('modeling')._sheet._elementRegistry.get('DecisionRule_049xiav')