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 97d16d07cae461de1f7a8bb92874287785373f31..d25bbe5016a31cdbdea1bb96bcd66ae8f0b17a33 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 @@ -2,6 +2,7 @@ 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.VDmnDecisionTable; import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnValue; import java.util.HashMap; @@ -11,7 +12,8 @@ import org.apache.commons.lang3.Validate; /** * A verification result entry element represents one dmn tabel / rule / column or single cell of - * the dmn. The identification of this elements works with {@link VerificationResultEntryElement#getIdentifier()}. + * the dmn. The identification of this elements works with {@link + * VerificationResultEntryElement#getIdentifier()}. */ public class VerificationResultEntryElement extends AbstractResultObject { @@ -36,6 +38,7 @@ public class VerificationResultEntryElement extends AbstractResultObject { * VDmnValue}. Call {@link VerificationResultEntryElement#withIdentifier(AbstractId)} to add * further identifier. * + * @param vDmnValue the {@link VDmnValue} * @return the new {@link VerificationResultEntryElement} */ public static VerificationResultEntryElement create(VDmnValue vDmnValue) { @@ -53,6 +56,7 @@ public class VerificationResultEntryElement extends AbstractResultObject { * VDmnDecisionTable}. Call {@link VerificationResultEntryElement#withIdentifier(AbstractId)} to * add further identifier. * + * @param dmnDecisionTable the {@link VDmnDecisionTable} * @return the new {@link VerificationResultEntryElement} */ public static VerificationResultEntryElement create(VDmnDecisionTable dmnDecisionTable) { @@ -62,6 +66,22 @@ public class VerificationResultEntryElement extends AbstractResultObject { .withIdentifier(dmnDecisionTable.getDecisionTableId()); } + /** + * Create a new {@link VerificationResultEntryElement} with the initial identifier from a {@link + * VDmnColumn}. Call {@link VerificationResultEntryElement#withIdentifier(AbstractId)} to add + * further identifier. + * + * @param column the {@link VDmnColumn} + * @return the new {@link VerificationResultEntryElement} + */ + public static VerificationResultEntryElement create(VDmnColumn column) { + return new VerificationResultEntryElement() + .withIdentifier(column.getDmnDefinition().getDefinitionId()) + .withIdentifier(column.getDmnDecision().getDecisionId()) + .withIdentifier(column.getDmnDecisionTable().getDecisionTableId()) + .withIdentifier(column.getColumnId()); + } + /** * Get all required ids ({@link AbstractId}) of the {@link VerificationResultEntryElement}. * @@ -78,7 +98,7 @@ public class VerificationResultEntryElement extends AbstractResultObject { * added twice. * * @param value the {@link AbstractId}, which must be annotated with the {@link JsonIdentifier} - * class + * class * @return the current {@link VerificationResultEntryElement} */ public VerificationResultEntryElement withIdentifier(AbstractId value) { 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 b61cd0cf3c701afdee258a35f2ca297d4b4a2273..43d7797930ea92f104ba73ac1f5eca405537ae38 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.INPUT_COLUMN; 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; import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionScope.RULE; import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionType.SHOW; @@ -16,6 +18,8 @@ public class Action extends AbstractResultObject { public static Action ACTION_SHOW_RULES; public static Action ACTION_SHOW_INPUT_ENTRIES; public static Action ACTION_SHOW_OUTPUT_ENTRIES; + public static Action ACTION_SHOW_INPUT_COLUMNS; + public static Action ACTION_SHOW_OUTPUT_COLUMNS; static { ACTION_SHOW_RULES = getBuilder().withActionType(SHOW).withActionScope(RULE).build(); @@ -23,6 +27,10 @@ public class Action extends AbstractResultObject { getBuilder().withActionType(SHOW).withActionScope(INPUT_ENTRY).build(); ACTION_SHOW_OUTPUT_ENTRIES = getBuilder().withActionType(SHOW).withActionScope(OUTPUT_ENTRY).build(); + ACTION_SHOW_INPUT_COLUMNS = + getBuilder().withActionType(SHOW).withActionScope(INPUT_COLUMN).build(); + ACTION_SHOW_OUTPUT_COLUMNS = + getBuilder().withActionType(SHOW).withActionScope(OUTPUT_COLUMN).build(); } private ActionType actionType; 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 ebedbed73b479caae5cf0227d8185a0f3e0d1c58..32f837e0fdb44110d8c3aaca55e344e8f3352b9d 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,6 +1,8 @@ package de.unikoblenz.fgbks.core.dmn.verification.result.actions; +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_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; @@ -18,6 +20,8 @@ public class VerificationFix { public static VerificationFix SHOW_RULES; public static VerificationFix SHOW_INPUT_ENTRIES; public static VerificationFix SHOW_OUTPUT_ENTRIES; + public static VerificationFix SHOW_INPUT_COLUMNS; + public static VerificationFix SHOW_OUTPUT_COLUMNS; static { SHOW_RULES = @@ -35,6 +39,16 @@ public class VerificationFix { .withFixName(DEFAULT_SHOW_NAME) .addAction(ACTION_SHOW_OUTPUT_ENTRIES) .build(); + SHOW_INPUT_COLUMNS = + VerificationFix.getBuilder() + .withFixName(DEFAULT_SHOW_NAME) + .addAction(ACTION_SHOW_INPUT_COLUMNS) + .build(); + SHOW_OUTPUT_COLUMNS = + VerificationFix.getBuilder() + .withFixName(DEFAULT_SHOW_NAME) + .addAction(ACTION_SHOW_OUTPUT_COLUMNS) + .build(); } private Name fixName; diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/PredefinedMissingValueVerifier.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/PredefinedMissingValueVerifier.java new file mode 100644 index 0000000000000000000000000000000000000000..4dc9443b15073f6e7dc0b6f80e54c47266b773ee --- /dev/null +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/PredefinedMissingValueVerifier.java @@ -0,0 +1,95 @@ +package de.unikoblenz.fgbks.core.dmn.verification.verifier.impl; + +import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.VerificationFix.SHOW_INPUT_COLUMNS; +import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.VerificationFix.SHOW_OUTPUT_COLUMNS; + +import de.unikoblenz.fgbks.base.domain.StringValue; +import de.unikoblenz.fgbks.base.utils.boundary.impl.StringBoundary; +import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnColumn; +import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnInputValue; +import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnOutputValue; +import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnValue; +import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VTypeRef; +import de.unikoblenz.fgbks.core.dmn.domain.vdmn.utils.VDmnFunctions; +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.PredefinedMissingValueVerification; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +@DmnVerifier(verifierType = PredefinedMissingValueVerification.class) +public class PredefinedMissingValueVerifier extends AbstractVerifier { + + @Override + protected void doVerification() { + for (VDmnColumn stringColumn : + VDmnFunctions.getColumnsByTypeRef( + dmnObjectContainer.getVDmnDefinition(), VTypeRef.STRING)) { + checkStringColumns(stringColumn); + } + } + + private void checkStringColumns(VDmnColumn stringColumn) { + // Check, if there are PredefinedValues defined + boolean predefinedValuesArePresent = stringColumn.getPredefinedValues().isPresent(); + Set<String> predefinedValues = new HashSet<>(); + if (predefinedValuesArePresent) { + predefinedValues = + stringColumn.getPredefinedValues().get().stream() + .map(StringValue::getValue) + .collect(Collectors.toSet()); + } + // Add all string values from the entries + Set<String> stringValuesInColumn = new HashSet<>(); + for (VDmnValue stringValue : stringColumn.getValues()) { + // do not check empty values + if (!stringValue.getText().getValue().isEmpty()) { + if (stringValue.isInputValue()) { + stringValuesInColumn.addAll(getStringValues((VDmnInputValue) stringValue)); + } else { + stringValuesInColumn.addAll(getStringValues((VDmnOutputValue) stringValue)); + } + } + } + // get all missing strings + Set<String> missingStrings = new HashSet<>(); + for (String s : stringValuesInColumn) { + if (!predefinedValues.contains(s)) { + missingStrings.add(s); + } + } + if (missingStrings.size() > 0) { + addToResult(stringColumn, missingStrings); + } + } + + private Set<String> getStringValues(VDmnOutputValue stringValue) { + String parsedOutputText = stringValue.getText().getValue().replace('"', '\0').trim(); + return Collections.singleton(parsedOutputText); + } + + private Set<String> getStringValues(VDmnInputValue stringValue) { + if (stringValue.getBoundary() instanceof StringBoundary) { + StringBoundary sb = (StringBoundary) stringValue.getBoundary(); + return new HashSet<>(Arrays.asList(sb.getValues())); + } + return Collections.emptySet(); + } + + private void addToResult(VDmnColumn stringColumn, Set<String> missingStringValues) { + vreFactory.addElement(VerificationResultEntryElement.create(stringColumn)); + vreFactory.addVerificationFix( + stringColumn.isInputColumn() ? SHOW_INPUT_COLUMNS : SHOW_OUTPUT_COLUMNS); + StringBuilder sb = new StringBuilder(); + sb.append(missingStringValues.size() > 1 ? "These string values are" : "This string value is"); + sb.append(" not present in the predefined values of the column: "); + sb.append( + missingStringValues.stream().map(v -> '"' + v + '"').collect(Collectors.joining(","))); + vreFactory.addToEntry(VerificationClassification.WARNING, sb.toString()); + } +} diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/PredefinedMissingValueVerification.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/PredefinedMissingValueVerification.java new file mode 100644 index 0000000000000000000000000000000000000000..5e1026be663aa41f95d6bff4944655c5e757d317 --- /dev/null +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/types/PredefinedMissingValueVerification.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.ModelingLevelVerification; +import javax.validation.constraints.NotNull; + +@Type +public class PredefinedMissingValueVerification extends AbstractVerificationType { + + private static final PredefinedMissingValueVerification instance = + new PredefinedMissingValueVerification(); + + private PredefinedMissingValueVerification() { + super( + new Name("PredefinedMissingValueVerification"), + new Description( + "Es gibt in einer Tabellen-Zelle predefines values, die jedoch nicht in der spalte vorhanden sind.")); // TODO englisch + } + + public static PredefinedMissingValueVerification getInstance() { + return instance; + } + + @Override + public @NotNull ClassificationType getClassification() { + return ModelingLevelVerification.getInstance(); + } +}