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

Merge branch 'develop' into 'master'

Develop

See merge request fg-bks/br-verification-tool!6
parents 6881e240 f35bb75c
No related branches found
No related tags found
No related merge requests found
Showing
with 172 additions and 91 deletions
......@@ -38,12 +38,6 @@
<dependencies>
<!-- logging framework -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.7</version>
</dependency>
<!-- camunda dmn engine -->
<dependency>
<groupId>org.camunda.bpm.dmn</groupId>
......@@ -125,7 +119,7 @@
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<filtering>false</filtering> <!-- not needed yet -->
</resource>
</resources>
<plugins>
......@@ -171,4 +165,4 @@
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
</project>
......@@ -2,11 +2,10 @@ package de.unikoblenz.fgbks.base.utils;
import java.io.Serializable;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Performance
@Interceptor
......@@ -19,7 +18,7 @@ public class PerformanceInterceptor implements Serializable {
long end = System.nanoTime();
long durationInMs = TimeUnit.NANOSECONDS.toMillis(end - start);
Logger log = LoggerFactory.getLogger(ctx.getMethod().getDeclaringClass());
Logger log = Logger.getLogger(ctx.getMethod().getDeclaringClass().getSimpleName());
log.info(ctx.getMethod().getName() + " - " + durationInMs + " ms");
return obj;
}
......
......@@ -4,19 +4,18 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Objects;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import org.apache.commons.io.IOUtils;
import org.primefaces.model.UploadedFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SessionScoped
public class DmnBean implements Serializable {
private String dmnXML;
private static Logger LOGGER = LoggerFactory.getLogger(DmnBean.class.getSimpleName());
private static Logger LOGGER = Logger.getLogger(DmnBean.class.getSimpleName());
@PostConstruct
void init() {
......
package de.unikoblenz.fgbks.dmn.beans;
import de.unikoblenz.fgbks.base.wordnet.WordnetService;
import java.util.logging.Logger;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Destroyed;
import javax.enterprise.context.Initialized;
import javax.enterprise.event.Observes;
import javax.servlet.ServletContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ApplicationScoped
public class StartupListener {
private static Logger LOGGER = LoggerFactory.getLogger(StartupListener.class.getSimpleName());
private static Logger LOGGER = Logger.getLogger(StartupListener.class.getSimpleName());
public void init(@Observes @Initialized(ApplicationScoped.class) ServletContext context) {
// init wordnet
......
......@@ -2,6 +2,7 @@ package de.unikoblenz.fgbks.dmn.core.models;
import de.unikoblenz.fgbks.base.builder.DefaultBuilder;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import javax.xml.bind.annotation.XmlElement;
......@@ -31,5 +32,11 @@ public class VerifierCollectionResult {
value.verifierResults.add(Objects.requireNonNull(verificationResult));
return this;
}
@Override
public VerifierCollectionResult build() {
value.verifierResults.sort(Comparator.comparing(v -> v.getVerifierType().name()));
return super.build();
}
}
}
package de.unikoblenz.fgbks.dmn.core.models;
import de.unikoblenz.fgbks.dmn.core.models.VerifierCollectionResult.Builder;
import de.unikoblenz.fgbks.dmn.core.verifier.*;
import de.unikoblenz.fgbks.dmn.core.verifier.helper.RuleMap;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import org.camunda.bpm.dmn.engine.DmnDecision;
......@@ -44,11 +46,14 @@ public enum VerifierType {
public static VerifierCollectionResult getAllResults(List<DmnDecision> dmnDecisionList) {
RuleMap ruleMap = RuleMap.createMapFromDmn(dmnDecisionList);
VerifierCollectionResult.Builder builder = VerifierCollectionResult.getBuilder();
for (VerifierType verifierType : values()) {
// TODO: make multi-thread
verifierType.getResult(dmnDecisionList, ruleMap).ifPresent(builder::addVerification);
}
Builder builder = VerifierCollectionResult.getBuilder();
Arrays.asList(values())
.parallelStream()
.forEach(
verifierType ->
verifierType
.getResult(dmnDecisionList, ruleMap)
.ifPresent(builder::addVerification));
return builder.build();
}
}
package de.unikoblenz.fgbks.dmn.core.verifier;
import de.unikoblenz.fgbks.dmn.core.models.RuleIdentifier;
import de.unikoblenz.fgbks.dmn.core.models.VerificationResult;
import de.unikoblenz.fgbks.dmn.core.models.VerifierResult;
import de.unikoblenz.fgbks.dmn.core.models.VerifierType;
import de.unikoblenz.fgbks.dmn.core.verifier.helper.RuleMap;
import de.unikoblenz.fgbks.dmn.core.verifier.helper.Type;
import de.unikoblenz.fgbks.dmn.core.verifier.helper.Value;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.logging.Logger;
import org.camunda.bpm.dmn.engine.DmnDecision;
......@@ -54,4 +58,19 @@ public abstract class AbstractVerifier {
protected final void addVerification(VerificationResult verificationResult) {
verifierResultBuilder.addVerificationResult(Objects.requireNonNull(verificationResult));
}
protected boolean checkDifferentConclusion(
String decisionKey, List<RuleIdentifier> currentRuleIdentifiers) {
Set<Type> outputCols =
ruleMap.getAllOutputTypesFromDecisionKey(Objects.requireNonNull(decisionKey));
for (Type outputType : outputCols) {
List<Value> values =
ruleMap.getValuesFromOutputType(
outputType, Objects.requireNonNull(currentRuleIdentifiers));
if (values.stream().map(Value::getBoundary).distinct().limit(2).count() > 1) {
return true;
}
}
return false;
}
}
......@@ -39,7 +39,12 @@ public class IdenticalRules extends AbstractVerifier {
List<Type> inputs, int i, List<RuleIdentifier> currentRuleIdentifiers) {
if (i == inputs.size()) {
VerificationResult.Builder vBuilder =
VerificationResult.getBuilder().withMessage(getMessageText(currentRuleIdentifiers));
VerificationResult.getBuilder()
.withMessage(
getMessageText(
currentRuleIdentifiers,
checkDifferentConclusion(
currentRuleIdentifiers.get(0).getDecisionKey(), currentRuleIdentifiers)));
vBuilder.addRules(currentRuleIdentifiers);
addVerification(vBuilder.build());
} else {
......@@ -81,7 +86,8 @@ public class IdenticalRules extends AbstractVerifier {
@Override
protected void afterVerifyDecision() {}
private String getMessageText(List<RuleIdentifier> currentRuleIdentifiers) {
private String getMessageText(
List<RuleIdentifier> currentRuleIdentifiers, boolean isDifferentConclusion) {
StringBuilder sb = new StringBuilder("Rules ");
sb.append(
currentRuleIdentifiers
......@@ -91,6 +97,11 @@ public class IdenticalRules extends AbstractVerifier {
sb.append(" in table ");
sb.append(currentRuleIdentifiers.get(0).getTableName());
sb.append(" are identical.");
if (isDifferentConclusion) {
sb.append(" The output has different conclusions!");
} else {
sb.append(" The output is the same.");
}
return sb.toString();
}
}
......@@ -31,9 +31,16 @@ public class OverlappingRules extends AbstractVerifier {
private void checkForOverlappingRules(
List<Type> inputs, int i, List<RuleIdentifier> currentRuleIdentifiers, boolean hasOverlap) {
if (i == inputs.size()) {
// do nothing, if there was no real overlap found prev..
if (hasOverlap) {
VerificationResult.Builder vBuilder =
VerificationResult.getBuilder().withMessage(getMessageText(currentRuleIdentifiers));
VerificationResult.getBuilder()
.withMessage(
getMessageText(
currentRuleIdentifiers,
checkDifferentConclusion(
currentRuleIdentifiers.get(0).getDecisionKey(),
currentRuleIdentifiers)));
vBuilder.addRules(currentRuleIdentifiers);
addVerification(vBuilder.build());
}
......@@ -42,38 +49,42 @@ public class OverlappingRules extends AbstractVerifier {
List<Value> sortedBounds =
new ArrayList<>(ruleMap.getValuesFromInputType(inputs.get(i), currentRuleIdentifiers));
sortedBounds.sort(Comparator.comparing(Value::getBoundary));
Value lastBound = null;
boolean foundOverlap = false;
int z = 0;
for (Value currentBound : sortedBounds) {
if (lastBound != null) {
boolean isOverlap =
currentBound.getBoundary().isBoundaryOverlapping(lastBound.getBoundary());
if (isOverlap || ! currentBound.getBoundary().isBoundaryNotInContact(lastBound.getBoundary())) {
currentBounds.add(lastBound);
if (isOverlap) {
foundOverlap = true;
}
z++;
boolean foundOverlap = hasOverlap;
// copy of current bounds
List<Value> currentBoundsCpy = new ArrayList<>(currentBounds);
// add current bound to overlapping bounds
currentBounds.add(currentBound);
// check, if current bound is overlapping an other bound in the current list of overlapping
// rules
boolean foundNotInContact = false;
for (int x = 0; x < currentBounds.size(); x++) {
Value bound = currentBounds.get(x);
if (currentBound.getBoundary().isBoundaryNotInContact(bound.getBoundary())) {
currentBounds.remove(x--);
foundNotInContact = true;
} else {
if (currentBounds.size() > 0) {
currentBounds.add(lastBound);
checkForOverlappingRules(
inputs,
i + 1,
currentBounds.stream().map(Value::getRuleIdentifier).collect(Collectors.toList()),
foundOverlap || hasOverlap);
}
currentBounds.clear();
foundOverlap =
foundOverlap
|| currentBound.getBoundary().isBoundaryOverlapping(bound.getBoundary());
}
}
lastBound = currentBound;
}
if (currentBounds.size() > 0) {
currentBounds.add(lastBound);
checkForOverlappingRules(
inputs,
i + 1,
currentBounds.stream().map(Value::getRuleIdentifier).collect(Collectors.toList()),
foundOverlap || hasOverlap);
if (foundNotInContact) {
checkForOverlappingRules(
inputs,
i + 1,
currentBoundsCpy.stream().map(Value::getRuleIdentifier).collect(Collectors.toList()),
hasOverlap);
}
if (z == sortedBounds.size() && currentBounds.size() > 1) {
checkForOverlappingRules(
inputs,
i + 1,
currentBounds.stream().map(Value::getRuleIdentifier).collect(Collectors.toList()),
hasOverlap || foundOverlap);
}
}
}
}
......@@ -81,7 +92,8 @@ public class OverlappingRules extends AbstractVerifier {
@Override
protected void afterVerifyDecision() {}
private String getMessageText(List<RuleIdentifier> currentRuleIdentifiers) {
private String getMessageText(
List<RuleIdentifier> currentRuleIdentifiers, boolean isDifferentConclusion) {
StringBuilder sb = new StringBuilder("Rules ");
sb.append(
currentRuleIdentifiers
......@@ -89,6 +101,11 @@ public class OverlappingRules extends AbstractVerifier {
.map(c -> c.getRowNumber().toString())
.collect(Collectors.joining(", ")));
sb.append(" are overlapping.");
if (isDifferentConclusion) {
sb.append(" The output has different conclusions!");
} else {
sb.append(" The output is the same.");
}
return sb.toString();
}
}
......@@ -41,7 +41,13 @@ public class SubsumptionRules extends AbstractVerifier {
if (hasSubsumption) {
VerificationResult.Builder vBuilder =
VerificationResult.getBuilder()
.withMessage(getMessageText(currentRuleIdentifiers, currentRootSubsumptionElement));
.withMessage(
getMessageText(
currentRuleIdentifiers,
currentRootSubsumptionElement,
checkDifferentConclusion(
currentRootSubsumptionElement.getRuleIdentifier().getDecisionKey(),
currentRuleIdentifiers)));
vBuilder.addRules(currentRuleIdentifiers);
addVerification(vBuilder.build());
}
......@@ -72,7 +78,7 @@ public class SubsumptionRules extends AbstractVerifier {
for (Value cb2 : selectedBounds) {
boolean fs = nValue.getBoundary().isBoundarySubsumptionOf(cb2.getBoundary());
foundSubsumption |= fs;
if (fs) {
if (fs || nValue.getBoundary().isBoundaryEquals(cb2.getBoundary())) {
c1.add(cb2);
}
}
......@@ -91,31 +97,37 @@ public class SubsumptionRules extends AbstractVerifier {
for (Value cb2 : selectedBounds) {
boolean fs = cb1.getBoundary().isBoundarySubsumptionOf(cb2.getBoundary());
foundSubsumption |= fs;
if (fs) {
if (fs || cb1.getBoundary().isBoundaryEquals(cb2.getBoundary())) {
c1.add(cb2);
}
}
if (c1.size() > 1) {
clusters.add(c1);
subsumptions.add(foundSubsumption);
subsumptionValue.add(cb1);
if (foundSubsumption) {
subsumptionValue.add(cb1);
} else {
subsumptionValue.add(null);
}
}
}
}
// check for subsets, that includes other subsets and remove them
for (int x = 0; x < clusters.size(); x++) {
if (clusters.get(x) != null) {
Set<Value> c1 = clusters.get(x);
for (int y = 0; y < clusters.size(); y++) {
for (int y = x + 1; y < clusters.size(); y++) {
if (clusters.get(y) != null) {
Set<Value> c2 = clusters.get(y);
if (c1.containsAll(c2) && x != y) {
if (c1.containsAll(c2) && c2.containsAll(c1)) {
clusters.set(y, null);
}
}
}
}
}
// recursively search next row for subsumption with all clusters
for (int x = 0; x < clusters.size(); x++) {
if (clusters.get(x) != null) {
......@@ -135,7 +147,9 @@ public class SubsumptionRules extends AbstractVerifier {
protected void afterVerifyDecision() {}
private String getMessageText(
List<RuleIdentifier> currentRuleIdentifiers, Value subsumptionRule) {
List<RuleIdentifier> currentRuleIdentifiers,
Value subsumptionRule,
boolean isDifferentConclusion) {
StringBuilder sb = new StringBuilder();
sb.append("In table ");
sb.append(subsumptionRule.getRuleIdentifier().getTableName());
......@@ -153,6 +167,11 @@ public class SubsumptionRules extends AbstractVerifier {
.map(c -> c.getRowNumber().toString())
.collect(Collectors.joining(", ")));
sb.append(".");
if (isDifferentConclusion) {
sb.append(" The output has different conclusions!");
} else {
sb.append(" The output is the same.");
}
return sb.toString();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/DMN/20151101/dmn.xsd" xmlns:biodi="http://bpmn.io/schema/dmn/biodi/1.0" id="Definitions_1kjh9a2" name="DRD" namespace="http://camunda.org/schema/1.0/dmn">
<decision id="Decision_13nychf" name="Identical test">
<decision id="Decision_13nychf" name="Identical">
<extensionElements>
<biodi:bounds x="121" y="77" width="180" height="80" />
<biodi:bounds x="127" y="130" width="180" height="80" />
</extensionElements>
<decisionTable id="decisionTable_1">
<input id="input_1">
......@@ -73,7 +73,7 @@
</rule>
</decisionTable>
</decision>
<decision id="Decision_1vo386g" name="Subsumption test 1">
<decision id="Decision_1vo386g" name="Subsumption 1">
<extensionElements>
<biodi:bounds x="344" y="74" width="180" height="80" />
</extensionElements>
......@@ -116,7 +116,7 @@
</rule>
</decisionTable>
</decision>
<decision id="Decision_19xi89b" name="Subsumption test 2">
<decision id="Decision_19xi89b" name="Subsumption 2">
<extensionElements>
<biodi:bounds x="343" y="178" width="180" height="80" />
</extensionElements>
......@@ -198,7 +198,7 @@
</rule>
</decisionTable>
</decision>
<decision id="Decision_1be8xb9" name="Equivalent rules">
<decision id="Decision_1be8xb9" name="Equivalent">
<extensionElements>
<biodi:bounds x="561" y="131" width="180" height="80" />
</extensionElements>
......@@ -247,9 +247,25 @@
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_192865k">
<inputEntry id="UnaryTests_1opozrj">
<text>"organisation"</text>
</inputEntry>
<outputEntry id="LiteralExpression_09euqzg">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_1kecqha">
<inputEntry id="UnaryTests_065gcy5">
<text>"organization"</text>
</inputEntry>
<outputEntry id="LiteralExpression_0idnc1m">
<text></text>
</outputEntry>
</rule>
</decisionTable>
</decision>
<decision id="Decision_0daxsth" name="Overlapping rules">
<decision id="Decision_0daxsth" name="Overlapping">
<extensionElements>
<biodi:bounds x="768" y="132" width="180" height="80" />
</extensionElements>
......@@ -257,11 +273,19 @@
<input id="InputClause_0l9m2o0">
<inputExpression id="LiteralExpression_1srvac8" typeRef="integer" />
</input>
<input id="InputClause_07r6jma">
<inputExpression id="LiteralExpression_1xe1qpo" typeRef="string">
<text></text>
</inputExpression>
</input>
<output id="OutputClause_02zjru8" typeRef="string" />
<rule id="DecisionRule_0tlti3q">
<inputEntry id="UnaryTests_1epuvm6">
<text>&lt;=20</text>
</inputEntry>
<inputEntry id="UnaryTests_0n8ezy2">
<text>"a"</text>
</inputEntry>
<outputEntry id="LiteralExpression_0p41xhl">
<text></text>
</outputEntry>
......@@ -270,36 +294,21 @@
<inputEntry id="UnaryTests_1bvpeoa">
<text>&gt;=20</text>
</inputEntry>
<inputEntry id="UnaryTests_1uquwtd">
<text></text>
</inputEntry>
<outputEntry id="LiteralExpression_1k69z44">
<text></text>
</outputEntry>
</rule>
</decisionTable>
</decision>
<decision id="Decision_1mjix3c" name="Identical test 2">
<extensionElements>
<biodi:bounds x="120" y="189" width="180" height="80" />
</extensionElements>
<decisionTable id="DecisionTable_1ndo00u">
<input id="InputClause_0ullwt4">
<inputExpression id="LiteralExpression_0at3xrm" typeRef="integer">
<text>testNumber</text>
</inputExpression>
</input>
<input id="InputClause_0wjsaiy">
<inputExpression id="LiteralExpression_0kvzk24" typeRef="string">
<text>testString</text>
</inputExpression>
</input>
<output id="OutputClause_1h8uwwl" typeRef="string" />
<rule id="DecisionRule_06iq2ey">
<inputEntry id="UnaryTests_0pt1lz0">
<text>=10</text>
<rule id="DecisionRule_01r47t2">
<inputEntry id="UnaryTests_1w53rod">
<text>[10..30]</text>
</inputEntry>
<inputEntry id="UnaryTests_1vaw0zi">
<text>"Hallo"</text>
<inputEntry id="UnaryTests_1f92137">
<text>"b"</text>
</inputEntry>
<outputEntry id="LiteralExpression_09yp5x6">
<outputEntry id="LiteralExpression_1d7bwj8">
<text></text>
</outputEntry>
</rule>
......
......@@ -36,10 +36,12 @@ html, body {
margin: 15px;
width: 160px;
height: 35px;
cursor: pointer;
}
.ruleselect-button {
margin: 3px;
cursor: pointer;
}
#content-dmn {
......
......@@ -12,5 +12,6 @@ class WordnetServiceTest {
assertTrue(wns.areNounsSynonyms("bill", "invoice"));
assertTrue(wns.areNounsSynonyms("exam", "examination"));
assertTrue(wns.areNounsSynonyms("test", "examination"));
assertTrue(wns.areNounsSynonyms("organisation", "organization"));
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment