Skip to content
Snippets Groups Projects
Commit 9ae33d7d authored by Jonas Blatt's avatar Jonas Blatt :ant:
Browse files

Merge branch 'feature/verifieractions' into 'documentation/verifier'

Feature/verifieractions

See merge request jonasblatt/ma-jonasblatt-dmn-verifier!101
parents d42d8fbe c2468399
No related branches found
No related tags found
No related merge requests found
Showing
with 158 additions and 134 deletions
......@@ -110,14 +110,12 @@ public class DoubleBoundary extends AbstractGrowingBoundary<Double> {
upperBound = Double.parseDouble(text);
lowerBound = getMinValue();
lowerBoundType = INCLUSIVE;
} else if (text.startsWith("=")) {
} else {
text = text.replace('=', '\0').trim();
upperBound = Double.parseDouble(text);
lowerBound = Double.parseDouble(text);
lowerBoundType = INCLUSIVE;
upperBoundType = INCLUSIVE;
} else {
throw new BoundaryParseException();
}
} catch (Exception e) {
throw new BoundaryParseException(
......
......@@ -112,14 +112,12 @@ public class IntegerBoundary extends AbstractGrowingBoundary<Integer> {
upperBound = Integer.parseInt(text);
lowerBound = getMinValue();
lowerBoundType = INCLUSIVE;
} else if (text.startsWith("=")) {
} else {
text = text.replace('=', '\0').trim();
upperBound = Integer.parseInt(text);
lowerBound = Integer.parseInt(text);
lowerBoundType = INCLUSIVE;
upperBoundType = INCLUSIVE;
} else {
throw new BoundaryParseException();
}
} catch (Exception e) {
throw new BoundaryParseException(
......
......@@ -111,14 +111,12 @@ public class LongBoundary extends AbstractGrowingBoundary<Long> {
upperBound = Long.parseLong(text);
lowerBound = getMinValue();
lowerBoundType = INCLUSIVE;
} else if (text.startsWith("=")) {
} else {
text = text.replace('=', '\0').trim();
upperBound = Long.parseLong(text);
lowerBound = Long.parseLong(text);
lowerBoundType = INCLUSIVE;
upperBoundType = INCLUSIVE;
} else {
throw new BoundaryParseException();
}
} catch (Exception e) {
throw new BoundaryParseException(
......
......@@ -118,11 +118,11 @@ public class StringBoundary extends AbstractBoundary<String> {
if (otherStringB.matchesAny() || otherStringB.matchesNoneOfValues()) {
return 0;
} else {
return -1;
return 1;
}
}
if (otherStringB.matchesAny() || otherStringB.matchesNoneOfValues()) {
return 1;
return -1;
}
return this.getValues()[0].compareTo(otherStringB.getValues()[0]);
}
......
......@@ -3,6 +3,7 @@ package de.unikoblenz.fgbks.core.dmn.verification.verifier.impl;
import static de.unikoblenz.fgbks.base.utils.boundary.impl.DateBoundary.dateGroupName;
import static de.unikoblenz.fgbks.base.utils.boundary.impl.DateBoundary.datePattern;
import static de.unikoblenz.fgbks.core.dmn.domain.vdmn.utils.VDmnFunctions.templateDecisionRule;
import static de.unikoblenz.fgbks.core.dmn.verification.result.VerificationResultEntry.VerificationClassification.FATAL_ERROR;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.VerificationFix.SHOW_INPUT_ENTRIES;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.VerificationFix.SHOW_OUTPUT_ENTRIES;
......@@ -10,7 +11,6 @@ import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnColumn;
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;
......@@ -64,7 +64,7 @@ public class DateVerifier extends AbstractVerifier {
vreFactory.addVerificationFix(
dateValue.isInputValue() ? SHOW_INPUT_ENTRIES : SHOW_OUTPUT_ENTRIES);
vreFactory.addToEntry(
VerificationClassification.FATAL_ERROR,
FATAL_ERROR,
templateDecisionRule(dateValue.getVDmnRule())
+ "Date value '%s' does not match 'date and time(\"yyyy-mm-ddTHH:MM:SS\").'",
dateStringValue);
......@@ -78,7 +78,7 @@ public class DateVerifier extends AbstractVerifier {
vreFactory.addVerificationFix(
dateValue.isInputValue() ? SHOW_INPUT_ENTRIES : SHOW_OUTPUT_ENTRIES);
vreFactory.addToEntry(
VerificationClassification.FATAL_ERROR,
FATAL_ERROR,
templateDecisionRule(dateValue.getVDmnRule())
+ "Date value '%s' has no valid date format.",
dateTime);
......
package de.unikoblenz.fgbks.core.dmn.verification.verifier.impl;
import static de.unikoblenz.fgbks.core.dmn.domain.vdmn.utils.VDmnFunctions.templateDecisionRule;
import static de.unikoblenz.fgbks.core.dmn.verification.result.VerificationResultEntry.VerificationClassification.WARNING;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.VerificationFix.SHOW_OUTPUT_ENTRIES;
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.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;
......@@ -34,7 +34,7 @@ public class EmptyOutputVerifier extends AbstractVerifier {
vreFactory.addElement(VerificationResultEntryElement.create(outputValue));
vreFactory.addVerificationFix(SHOW_OUTPUT_ENTRIES);
vreFactory.addToEntry(
VerificationClassification.WARNING,
WARNING,
templateDecisionRule(outputValue.getVDmnRule()) + "Output value is empty.'");
}
}
......
......@@ -68,19 +68,21 @@ public class EquivalentVerifier extends AbstractVerifier {
VDmnValue v1, VDmnValue v2, List<String> stringVals, List<String> stringValsInner) {
for (int i = 0; i < stringVals.size(); i++) {
for (int u = 0; u < stringValsInner.size(); u++) {
if (wordnetService.areNounsSynonyms(stringVals.get(i), stringValsInner.get(u))) {
vreFactory.addElement(VerificationResultEntryElement.create(v1));
vreFactory.addElement(VerificationResultEntryElement.create(v2));
vreFactory.addVerificationFix(
v1.isInputValue() ? SHOW_INPUT_ENTRIES : SHOW_OUTPUT_ENTRIES);
vreFactory.addToEntry(
VerificationClassification.WARNING,
templateDecisionColumn(v1.getVDmnColumn())
+ "String values \"%s\" (Row %s) and \"%s\" (Row %s) might be equivalent.",
stringVals.get(i),
v1.getVDmnRule().getRowNumber().toString(),
stringValsInner.get(u),
v2.getVDmnRule().getRowNumber().toString());
if (stringVals.get(i).length() > 1 && stringValsInner.get(u).length() > 1) {
if (wordnetService.areNounsSynonyms(stringVals.get(i), stringValsInner.get(u))) {
vreFactory.addElement(VerificationResultEntryElement.create(v1));
vreFactory.addElement(VerificationResultEntryElement.create(v2));
vreFactory.addVerificationFix(
v1.isInputValue() ? SHOW_INPUT_ENTRIES : SHOW_OUTPUT_ENTRIES);
vreFactory.addToEntry(
VerificationClassification.WARNING,
templateDecisionColumn(v1.getVDmnColumn())
+ "String values \"%s\" (Row %s) and \"%s\" (Row %s) might be equivalent.",
stringVals.get(i),
v1.getVDmnRule().getRowNumber().toString(),
stringValsInner.get(u),
v2.getVDmnRule().getRowNumber().toString());
}
}
}
}
......
......@@ -3,6 +3,8 @@ package de.unikoblenz.fgbks.core.dmn.verification.verifier.impl;
import static de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType.IS_EQUAL;
import static de.unikoblenz.fgbks.core.dmn.domain.vdmn.utils.VDmnFunctions.getRulesRowsStrings;
import static de.unikoblenz.fgbks.core.dmn.domain.vdmn.utils.VDmnFunctions.templateDecision;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionScope.RULE;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionType.DELETE;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.VerificationFix.SHOW_RULES;
import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnDecision;
......@@ -15,8 +17,6 @@ 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.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;
......@@ -59,15 +59,13 @@ public class IdenticalRuleVerifier extends AbstractVerifier {
if (sameConclusions) {
VerificationFix.Builder verificationFixBuilder =
VerificationFix.getBuilder().withFixName("Delete Duplicates");
Action.Builder actionBuilder =
Action.getBuilder().withActionScope(ActionScope.RULE).withActionType(ActionType.DELETE);
boolean first = true;
for (VDmnRule rule : currentRules) {
if (!first) {
verificationFixBuilder.addAction(
Action.getBuilder()
.withActionScope(ActionScope.RULE)
.withActionType(ActionType.DELETE)
.withActionScope(RULE)
.withActionType(DELETE)
.addIdValue(rule.getVDmnDecision().getDecisionId())
.addIdValue(rule.getRuleId())
.build());
......
package de.unikoblenz.fgbks.core.dmn.verification.verifier.impl;
import static de.unikoblenz.fgbks.core.dmn.domain.vdmn.utils.VDmnFunctions.templateDecisionRule;
import static de.unikoblenz.fgbks.core.dmn.verification.result.VerificationResultEntry.VerificationClassification.FATAL_ERROR;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.VerificationFix.SHOW_INPUT_ENTRIES;
import de.unikoblenz.fgbks.base.utils.boundary.impl.InvalidBoundary;
import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnInputValue;
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.verifier.AbstractVerifier;
import de.unikoblenz.fgbks.core.dmn.verification.verifier.DmnVerifier;
......@@ -33,7 +33,7 @@ public class InputValueSyntaxVerifier extends AbstractVerifier {
.addElement(VerificationResultEntryElement.create(inputValue))
.addVerificationFix(SHOW_INPUT_ENTRIES)
.addToEntry(
VerificationClassification.FATAL_ERROR,
FATAL_ERROR,
templateDecisionRule(inputValue.getVDmnRule())
+ "Input value is not valid: "
+ inputValue.getText());
......
package de.unikoblenz.fgbks.core.dmn.verification.verifier.impl;
import static de.unikoblenz.fgbks.core.dmn.domain.vdmn.utils.VDmnFunctions.getDecisionStringName;
import static de.unikoblenz.fgbks.core.dmn.verification.result.VerificationResultEntry.VerificationClassification.WARNING;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionScope.INPUT_DATA;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionType.DELETE;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionType.UPDATE;
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.VDmnDecision;
import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnInputColumn;
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.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;
......@@ -36,8 +37,8 @@ public class LonelyDataInputVerifier extends AbstractVerifier {
.withFixName(new Name("Remove"))
.addAction(
Action.getBuilder()
.withActionScope(ActionScope.INPUT_DATA)
.withActionType(ActionType.DELETE)
.withActionScope(INPUT_DATA)
.withActionType(DELETE)
.addIdValue(i.getInputDataId())
.build())
.build());
......@@ -45,7 +46,7 @@ public class LonelyDataInputVerifier extends AbstractVerifier {
searchPossibleDecisions(i);
// add to result
vreFactory.addToEntry(
VerificationClassification.WARNING,
WARNING,
"Input data \"%s\" has no outgoing connections to at least one decision node.",
i.getName().orElse(defaultName));
}
......@@ -64,8 +65,8 @@ public class LonelyDataInputVerifier extends AbstractVerifier {
.withFixName(new Name("Connect to " + getDecisionStringName(decision)))
.addAction(
Action.getBuilder()
.withActionScope(ActionScope.INPUT_DATA)
.withActionType(ActionType.UPDATE)
.withActionScope(INPUT_DATA)
.withActionType(UPDATE)
.addIdValue(inputColumn.getVDmnDecision().getDecisionId())
.addIdValue(inputData.getInputDataId())
.addValue("name", inputColumn.getName().get().getValue())
......
package de.unikoblenz.fgbks.core.dmn.verification.verifier.impl;
import static de.unikoblenz.fgbks.base.domain.Name.NO_NAME;
import static de.unikoblenz.fgbks.core.dmn.domain.vdmn.utils.VDmnFunctions.getDecisionStringName;
import static de.unikoblenz.fgbks.core.dmn.verification.result.VerificationResultEntry.VerificationClassification.WARNING;
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.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.OUTPUT_COLUMN;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionType.CREATE;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionType.DELETE;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.VerificationFix.DEFAULT_SHOW_NAME;
import de.unikoblenz.fgbks.base.domain.Name;
......@@ -10,11 +17,8 @@ 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;
......@@ -79,8 +83,8 @@ public class MissingInputColumnVerifier extends AbstractVerifier {
.addAction(
Action.getBuilder()
.addIdValue(inputDataNode.getId())
.withActionType(ActionType.DELETE)
.withActionScope(ActionScope.INPUT_DATA)
.withActionType(DELETE)
.withActionScope(INPUT_DATA)
.build())
.build());
}
......@@ -92,8 +96,8 @@ public class MissingInputColumnVerifier extends AbstractVerifier {
new Name("Add Input Column " + inputDataNode.getName().get().getValue()))
.addAction(
Action.getBuilder()
.withActionType(ActionType.CREATE)
.withActionScope(ActionScope.INPUT_COLUMN)
.withActionType(CREATE)
.withActionScope(INPUT_COLUMN)
.addIdValue(decision.getDecisionId())
.addValue("name", inputDataNode.getName().get().getValue())
.addValue("typeRef", "string")
......@@ -103,28 +107,45 @@ public class MissingInputColumnVerifier extends AbstractVerifier {
for (VDmnOutputColumn outputColumn :
((VDmnDecision) inputDataNode).getVDmnDecisionTable().getVDmnOutputColumns()) {
if (outputColumn.getName().isPresent()) {
// add input Column
vreFactory.addVerificationFix(
VerificationFix.getBuilder()
.withFixName(
new Name("Add Input Column " + outputColumn.getName().get().getValue()))
new Name("Add Input Column \"" + outputColumn.getName().get().getValue())
+ "\"")
.addAction(
Action.getBuilder()
.withActionType(ActionType.CREATE)
.withActionScope(ActionScope.INPUT_COLUMN)
.withActionType(CREATE)
.withActionScope(INPUT_COLUMN)
.addIdValue(decision.getDecisionId())
.addValue("name", outputColumn.getName().get().getValue())
.addValue("typeRef", outputColumn.getTypeRef().getName())
.build())
.build());
}
vreFactory.addVerificationFix(
VerificationFix.getBuilder()
.withFixName(
new Name(
"Delete Output Column \""
+ outputColumn.getName().orElse(NO_NAME).getValue())
+ "\"")
.addAction(
Action.getBuilder()
.withActionType(DELETE)
.withActionScope(OUTPUT_COLUMN)
.addIdValue(outputColumn.getVDmnDecision().getDecisionId())
.addIdValue(outputColumn.getOutputId())
.build())
.build());
}
}
vreFactory.addToEntry(
VerificationClassification.WARNING,
WARNING,
(inputDataNode.isInputData() ? "Input data" : "Decision")
+ " node \"%s\" has no corresponding input column in decision \"%s\"",
inputDataNode.getName().orElse(Name.NO_NAME),
inputDataNode.getName().orElse(NO_NAME),
getDecisionStringName(decision));
}
}
......
......@@ -3,6 +3,14 @@ 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.getDecisionStringName;
import static de.unikoblenz.fgbks.core.dmn.domain.vdmn.utils.VDmnFunctions.templateDecision;
import static de.unikoblenz.fgbks.core.dmn.verification.result.VerificationResultEntry.VerificationClassification.WARNING;
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.OUTPUT_COLUMN;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionType.CREATE;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionType.DELETE;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionType.UPDATE;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.VerificationFix.SHOW_INPUT_COLUMNS;
import de.unikoblenz.fgbks.base.domain.Name;
......@@ -11,11 +19,8 @@ import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnInputColumn;
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;
......@@ -69,30 +74,17 @@ public class MissingInputDataVerifier extends AbstractVerifier {
.addVerificationFix(SHOW_INPUT_COLUMNS);
// Action for creating input Data
if (inputColumn.getName().isPresent()) {
vreFactory
.addVerificationFix(
VerificationFix.getBuilder()
.withFixName(new Name("New Data Input"))
.addAction(
Action.getBuilder()
.withActionType(ActionType.CREATE)
.withActionScope(ActionScope.INPUT_DATA)
.addIdValue(inputColumn.getVDmnDecision().getDecisionId())
.addValue("name", inputColumn.getName().get().getValue())
.build())
.build())
// Action for deleting column
.addVerificationFix(
VerificationFix.getBuilder()
.withFixName(new Name("Delete Column"))
.addAction(
Action.getBuilder()
.withActionType(ActionType.DELETE)
.withActionScope(ActionScope.INPUT_COLUMN)
.addIdValue(inputColumn.getVDmnDecision().getDecisionId())
.addIdValue(inputColumn.getInputId())
.build())
.build());
vreFactory.addVerificationFix(
VerificationFix.getBuilder()
.withFixName(new Name("New Data Input"))
.addAction(
Action.getBuilder()
.withActionType(CREATE)
.withActionScope(INPUT_DATA)
.addIdValue(inputColumn.getVDmnDecision().getDecisionId())
.addValue("name", inputColumn.getName().get().getValue())
.build())
.build());
// Actions for connecting to existing input Data
searchPossibleInputData(inputColumn);
// Actions for connection to existing decisions
......@@ -100,9 +92,22 @@ public class MissingInputDataVerifier extends AbstractVerifier {
// Actions for creating output columns in connected decisions
searchPossibleConnectedDecisions(inputColumn);
}
vreFactory
// Action for deleting column
.addVerificationFix(
VerificationFix.getBuilder()
.withFixName(new Name("Delete Column"))
.addAction(
Action.getBuilder()
.withActionType(DELETE)
.withActionScope(INPUT_COLUMN)
.addIdValue(inputColumn.getVDmnDecision().getDecisionId())
.addIdValue(inputColumn.getInputId())
.build())
.build());
// Add to result
vreFactory.addToEntry(
VerificationClassification.WARNING,
WARNING,
templateDecision(inputColumn.getVDmnDecision())
+ "Input column \"%s\" has no input data node.",
getColumnStringName(inputColumn));
......@@ -117,8 +122,8 @@ public class MissingInputDataVerifier extends AbstractVerifier {
.withFixName(new Name("Connect to Input Data " + inputData.getName().get()))
.addAction(
Action.getBuilder()
.withActionType(ActionType.UPDATE)
.withActionScope(ActionScope.INPUT_DATA)
.withActionType(UPDATE)
.withActionScope(INPUT_DATA)
.addIdValue(inputColumn.getVDmnDecision().getDecisionId())
.addIdValue(inputData.getInputDataId())
.build())
......@@ -148,8 +153,8 @@ public class MissingInputDataVerifier extends AbstractVerifier {
+ getDecisionStringName(outputColumn.getVDmnDecision())))
.addAction(
Action.getBuilder()
.withActionType(ActionType.UPDATE)
.withActionScope(ActionScope.DECISION)
.withActionType(UPDATE)
.withActionScope(DECISION)
.addIdValue(outputColumn.getVDmnDecision().getDecisionId())
.addValue(
"targetDecisionId",
......@@ -169,8 +174,8 @@ public class MissingInputDataVerifier extends AbstractVerifier {
.withFixName("New Output Column in decision " + getDecisionStringName(decision))
.addAction(
Action.getBuilder()
.withActionType(ActionType.CREATE)
.withActionScope(ActionScope.OUTPUT_COLUMN)
.withActionType(CREATE)
.withActionScope(OUTPUT_COLUMN)
.addIdValue(decision.getDecisionId())
.addValue("name", inputColumn.getName().get().getValue())
.addValue("typeRef", inputColumn.getTypeRef().getName())
......
package de.unikoblenz.fgbks.core.dmn.verification.verifier.impl;
import static de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType.IS_IN_CONTACT;
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.VerificationResultEntry.VerificationClassification.WARNING;
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_OUTPUT_ENTRIES;
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;
......@@ -61,7 +62,7 @@ public class MissingInputValueVerifier extends AbstractVerifier {
}
Boundary b = outputColumn.getTypeRef().getBoundaryFromText(outputText);
for (VDmnInputValue inputValue : inputColumn.getVDmnInputValues()) {
if (b.checkWith(BoundaryCheckType.IS_IN_CONTACT, inputValue.getBoundary())) {
if (b.checkWith(IS_IN_CONTACT, inputValue.getBoundary())) {
continue outer;
}
}
......@@ -72,11 +73,11 @@ public class MissingInputValueVerifier extends AbstractVerifier {
.addVerificationFix(
VerificationFix.getBuilder()
.withFixName(DEFAULT_SHOW_NAME)
.addAction(Action.ACTION_SHOW_OUTPUT_ENTRIES)
.addAction(Action.ACTION_SHOW_INPUT_COLUMNS)
.addAction(ACTION_SHOW_OUTPUT_ENTRIES)
.addAction(ACTION_SHOW_INPUT_COLUMNS)
.build())
.addToEntry(
VerificationClassification.WARNING,
WARNING,
templateDecision(inputColumn.getVDmnDecision())
+ "Input column \"%s\" never handles the value '%s'.",
getColumnStringName(inputColumn),
......
package de.unikoblenz.fgbks.core.dmn.verification.verifier.impl;
import static de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType.IS_IN_CONTACT;
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;
......@@ -63,7 +63,7 @@ public class MissingOutputValueVerifier extends AbstractVerifier {
outputText = "= " + outputText;
}
Boundary b = outputColumn.getTypeRef().getBoundaryFromText(outputText);
if (b.checkWith(BoundaryCheckType.IS_IN_CONTACT, inputValue.getBoundary())) {
if (b.checkWith(IS_IN_CONTACT, inputValue.getBoundary())) {
continue outer;
}
}
......
package de.unikoblenz.fgbks.core.dmn.verification.verifier.impl;
import static de.unikoblenz.fgbks.base.utils.boundary.bicreater.BoundaryBiCreaterType.COMBINE;
import static de.unikoblenz.fgbks.base.utils.boundary.bicreater.BoundaryBiCreaterType.LOWER_BOUNDS;
import static de.unikoblenz.fgbks.base.utils.boundary.bicreater.BoundaryBiCreaterType.UPPER_BOUNDS;
import static de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType.IS_EQUAL;
import static de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType.IS_NOT_IN_CONTACT;
import static de.unikoblenz.fgbks.core.dmn.domain.vdmn.utils.VDmnFunctions.templateDecision;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionScope.RULE;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionType.CREATE;
import de.unikoblenz.fgbks.base.domain.Name;
import de.unikoblenz.fgbks.base.utils.UniqueIdGenerator;
import de.unikoblenz.fgbks.base.utils.boundary.Boundary;
import de.unikoblenz.fgbks.base.utils.boundary.bicreater.BoundaryBiCreaterType;
import de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType;
import de.unikoblenz.fgbks.core.dmn.domain.common.RowNumber;
import de.unikoblenz.fgbks.core.dmn.domain.ids.InputEntryId;
import de.unikoblenz.fgbks.core.dmn.domain.ids.RuleId;
......@@ -23,8 +29,6 @@ import de.unikoblenz.fgbks.core.dmn.domain.vdmn.impl.VDmnRuleImpl.Builder;
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;
......@@ -66,8 +70,8 @@ public class MissingRuleVerifier extends AbstractVerifier {
sb.append(" }");
Action.Builder fixActionBuilder =
Action.getBuilder()
.withActionScope(ActionScope.RULE)
.withActionType(ActionType.CREATE)
.withActionScope(RULE)
.withActionType(CREATE)
.addIdValue(missingRule.getVDmnDecision().getDecisionId());
for (VDmnInputValue v : missingRule.getVDmnInputValues()) {
fixActionBuilder.addValue(
......@@ -155,7 +159,7 @@ public class MissingRuleVerifier extends AbstractVerifier {
if (!inValsMissingRule
.get(i)
.getBoundary()
.checkWith(BoundaryCheckType.IS_EQUAL, inValsCurrentRule.get(i).getBoundary())) {
.checkWith(IS_EQUAL, inValsCurrentRule.get(i).getBoundary())) {
return false;
}
}
......@@ -197,7 +201,7 @@ public class MissingRuleVerifier extends AbstractVerifier {
missingInValues
.get(i)
.getBoundary()
.createBi(BoundaryBiCreaterType.LOWER_BOUNDS, currentValue.getBoundary()),
.createBi(LOWER_BOUNDS, currentValue.getBoundary()),
missingRule,
newMissingRules);
......@@ -208,7 +212,7 @@ public class MissingRuleVerifier extends AbstractVerifier {
missingInValues
.get(i)
.getBoundary()
.createBi(BoundaryBiCreaterType.UPPER_BOUNDS, currentValue.getBoundary()),
.createBi(UPPER_BOUNDS, currentValue.getBoundary()),
missingRule,
newMissingRules);
}
......@@ -258,7 +262,7 @@ public class MissingRuleVerifier extends AbstractVerifier {
if (inValsMissingRule
.get(i)
.getBoundary()
.checkWith(BoundaryCheckType.IS_NOT_IN_CONTACT, inValsCurrentRule.get(i).getBoundary())) {
.checkWith(IS_NOT_IN_CONTACT, inValsCurrentRule.get(i).getBoundary())) {
return false;
}
}
......@@ -282,8 +286,8 @@ public class MissingRuleVerifier extends AbstractVerifier {
VDmnInputValue v1 = inputValuesI.get(x);
VDmnInputValue v2 = inputValuesU.get(x);
newOBoundary =
v1.getBoundary().createBi(BoundaryBiCreaterType.COMBINE, v2.getBoundary());
if (v1.getBoundary().checkWith(BoundaryCheckType.IS_EQUAL, v2.getBoundary())) {
v1.getBoundary().createBi(COMBINE, v2.getBoundary());
if (v1.getBoundary().checkWith(IS_EQUAL, v2.getBoundary())) {
// nothing
} else if (newOBoundary.isPresent() && foundCombination == -1) {
newBoundary = newOBoundary.get();
......
......@@ -4,6 +4,7 @@ import static de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType.
import static de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType.IS_OVERLAPPING;
import static de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType.SUBSUMES;
import static de.unikoblenz.fgbks.core.dmn.domain.vdmn.utils.VDmnFunctions.getRulesRowsStrings;
import static de.unikoblenz.fgbks.core.dmn.verification.result.VerificationResultEntry.VerificationClassification.WARNING;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.VerificationFix.SHOW_RULES;
import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnDecision;
......@@ -13,7 +14,6 @@ import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnInputValue;
import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnRule;
import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnValue;
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;
......@@ -58,7 +58,7 @@ public class OverlappingVerifier extends AbstractVerifier {
rule -> vreFactory.addElement(VerificationResultEntryElement.create(rule)));
vreFactory.addVerificationFix(SHOW_RULES);
vreFactory.addToEntry(
VerificationClassification.WARNING,
WARNING,
VDmnFunctions.templateDecision(inColumns.get(0).getVDmnDecision())
+ "The rules %s are overlapping.",
getRulesRowsStrings(currentRules));
......
......@@ -5,6 +5,9 @@ import static de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType.
import static de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType.SUBSUMES;
import static de.unikoblenz.fgbks.core.dmn.domain.vdmn.utils.VDmnFunctions.getRulesRowsStrings;
import static de.unikoblenz.fgbks.core.dmn.domain.vdmn.utils.VDmnFunctions.templateDecision;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionScope.RULE;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionType.CREATE;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionType.DELETE;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.VerificationFix.SHOW_RULES;
import de.unikoblenz.fgbks.base.domain.Name;
......@@ -19,8 +22,6 @@ 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.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;
......@@ -158,8 +159,8 @@ public class PartialReductionVerifier extends AbstractVerifier {
}
Action.Builder fixActionBuilder =
Action.getBuilder()
.withActionScope(ActionScope.RULE)
.withActionType(ActionType.CREATE)
.withActionScope(RULE)
.withActionType(CREATE)
.addIdValue(inColumns.get(0).getVDmnDecision().getDecisionId());
for (int i = 0; i < inColumns.size(); i++) {
fixActionBuilder.addValue(
......@@ -178,15 +179,15 @@ public class PartialReductionVerifier extends AbstractVerifier {
.addAction(fixActionBuilder.build())
.addAction(
Action.getBuilder()
.withActionScope(ActionScope.RULE)
.withActionType(ActionType.DELETE)
.withActionScope(RULE)
.withActionType(DELETE)
.addIdValue(clusterRules.get(0).getVDmnDecision().getDecisionId())
.addIdValue(clusterRules.get(0).getRuleId())
.build())
.addAction(
Action.getBuilder()
.withActionScope(ActionScope.RULE)
.withActionType(ActionType.DELETE)
.withActionScope(RULE)
.withActionType(DELETE)
.addIdValue(clusterRules.get(1).getVDmnDecision().getDecisionId())
.addIdValue(clusterRules.get(1).getRuleId())
.build())
......
......@@ -5,6 +5,8 @@ import static de.unikoblenz.fgbks.core.dmn.verification.result.VerificationResul
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionScope.INPUT_COLUMN;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionScope.OUTPUT_COLUMN;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionScope.RULE;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionType.DELETE;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionType.UPDATE;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.VerificationFix.SHOW_INPUT_ENTRIES;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.VerificationFix.SHOW_OUTPUT_ENTRIES;
......@@ -18,7 +20,6 @@ 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.VerificationResultEntryElement;
import de.unikoblenz.fgbks.core.dmn.verification.result.actions.Action;
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;
......@@ -90,7 +91,7 @@ public class PredefinedExistingValueVerifier extends AbstractVerifier {
.withFixName("Add pred. value \"" + missingStringValue + "\"")
.addAction(
Action.getBuilder()
.withActionType(ActionType.UPDATE)
.withActionType(UPDATE)
.withActionScope(stringValue.isInputValue() ? INPUT_COLUMN : OUTPUT_COLUMN)
.addIdValue(stringValue.getDecisionId())
.addIdValue(stringValue.getVDmnColumn().getId())
......@@ -102,7 +103,7 @@ public class PredefinedExistingValueVerifier extends AbstractVerifier {
.withFixName("Delete rule " + stringValue.getVDmnRule().getRowNumber())
.addAction(
Action.getBuilder()
.withActionType(ActionType.DELETE)
.withActionType(DELETE)
.withActionScope(RULE)
.addIdValue(stringValue.getDecisionId())
.addIdValue(stringValue.getRuleId())
......
......@@ -4,6 +4,9 @@ import static de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType.
import static de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType.SUBSUMES;
import static de.unikoblenz.fgbks.core.dmn.domain.vdmn.utils.VDmnFunctions.getRulesRowsStrings;
import static de.unikoblenz.fgbks.core.dmn.domain.vdmn.utils.VDmnFunctions.templateDecision;
import static de.unikoblenz.fgbks.core.dmn.verification.result.VerificationResultEntry.VerificationClassification.WARNING;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionScope.RULE;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.ActionType.DELETE;
import static de.unikoblenz.fgbks.core.dmn.verification.result.actions.VerificationFix.SHOW_RULES;
import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnDecision;
......@@ -13,11 +16,8 @@ import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnInputValue;
import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnRule;
import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnValue;
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.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;
......@@ -61,16 +61,12 @@ public class SubsumptionVerifier extends AbstractVerifier {
if (!differentConclusions) {
VerificationFix.Builder verificationFixBuilder =
VerificationFix.getBuilder().withFixName("Delete subsumed Rules");
Action.Builder actionBuilder =
Action.getBuilder()
.withActionScope(ActionScope.RULE)
.withActionType(ActionType.DELETE);
for (VDmnRule rule : currentRules) {
if (!currentRootSubsumptionElements.contains(rule)) {
verificationFixBuilder.addAction(
Action.getBuilder()
.withActionScope(ActionScope.RULE)
.withActionType(ActionType.DELETE)
.withActionScope(RULE)
.withActionType(DELETE)
.addIdValue(rule.getVDmnDecision().getDecisionId())
.addIdValue(rule.getRuleId())
.build());
......@@ -83,7 +79,7 @@ public class SubsumptionVerifier extends AbstractVerifier {
.addVerificationFix(SHOW_RULES)
// Add to result
.addToEntry(
VerificationClassification.WARNING,
WARNING,
getMessageText(currentRules, currentRootSubsumptionElements, differentConclusions));
}
} else {
......
dmnverifierfrontend/src/main/resources/META-INF/resources/favicon.ico

40.7 KiB

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment