diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/checker/CheckEqualString.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/checker/CheckStringEqual.java similarity index 74% rename from dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/checker/CheckEqualString.java rename to dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/checker/CheckStringEqual.java index e27fa98094e2dbd870fb84d7dae34738ea9bffae..0c749655b1ac92ea12435649948619c1c9c5c7af 100644 --- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/checker/CheckEqualString.java +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/checker/CheckStringEqual.java @@ -2,11 +2,11 @@ package de.unikoblenz.fgbks.base.utils.boundary.checker; import de.unikoblenz.fgbks.base.utils.boundary.impl.StringBoundary; -public class CheckEqualString extends AbstractBoundaryCheck<StringBoundary> { +public class CheckStringEqual extends AbstractBoundaryCheck<StringBoundary> { - private static CheckEqualString instance = new CheckEqualString(); + private static CheckStringEqual instance = new CheckStringEqual(); - public static CheckEqualString getInstance() { + public static CheckStringEqual getInstance() { return instance; } @@ -17,6 +17,10 @@ public class CheckEqualString extends AbstractBoundaryCheck<StringBoundary> { @Override public boolean check(StringBoundary b1, StringBoundary b2) { + return checkEqual(b1, b2); + } + + public static boolean checkEqual(StringBoundary b1, StringBoundary b2) { if (b1 == b2 || b1.getText().equals(b2.getText()) || b1.isMatchAny() && b2.isMatchAny()) { return true; } diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/checker/CheckStringInContact.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/checker/CheckStringInContact.java new file mode 100644 index 0000000000000000000000000000000000000000..2a1e1ff9c796976bb55368bf7e9ce4662665866c --- /dev/null +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/checker/CheckStringInContact.java @@ -0,0 +1,53 @@ +package de.unikoblenz.fgbks.base.utils.boundary.checker; + +import de.unikoblenz.fgbks.base.utils.boundary.impl.StringBoundary; + +public class CheckStringInContact extends AbstractBoundaryCheck<StringBoundary> { + + private static CheckStringInContact instance = new CheckStringInContact(); + + public static CheckStringInContact getInstance() { + return instance; + } + + @Override + public BoundaryCheckType getType() { + return BoundaryCheckType.IS_IN_CONTACT; + } + + @Override + public boolean check(StringBoundary b1, StringBoundary b2) { + return checkInContact(b1, b2); + } + + public static boolean checkInContact(StringBoundary b1, StringBoundary b2) { + if (b1.isMatchAny() + || b2.isMatchAny() + || b1.isMatchNoneOfValues() && b2.isMatchNoneOfValues()) { + return true; + } + int[] b1h = b1.getValuesHashes(); + int[] b2h = b2.getValuesHashes(); + // both are not matching non values + if (!b1.isMatchNoneOfValues() && !b2.isMatchNoneOfValues()) { + for (int i : b1h) { + for (int u : b2h) { + if (i == u) { + return true; + } + } + } + return false; + } + // one is matching non values "not("a")" + if (b1h.length != b2h.length) { + return true; + } + for (int i = 0; i < b1h.length; i++) { + if (b1h[i] != b2h[i]) { + return true; + } + } + return false; + } +} diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/checker/CheckStringNotContact.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/checker/CheckStringNotContact.java new file mode 100644 index 0000000000000000000000000000000000000000..e514083762e85ec32af4898a3138d7bc7efe905f --- /dev/null +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/checker/CheckStringNotContact.java @@ -0,0 +1,26 @@ +package de.unikoblenz.fgbks.base.utils.boundary.checker; + +import de.unikoblenz.fgbks.base.utils.boundary.impl.StringBoundary; + +public class CheckStringNotContact extends AbstractBoundaryCheck<StringBoundary> { + + private static CheckStringNotContact instance = new CheckStringNotContact(); + + public static CheckStringNotContact getInstance() { + return instance; + } + + @Override + public BoundaryCheckType getType() { + return BoundaryCheckType.IS_NOT_IN_CONTACT; + } + + @Override + public boolean check(StringBoundary b1, StringBoundary b2) { + return checkNotInContact(b1, b2); + } + + public static boolean checkNotInContact(StringBoundary b1, StringBoundary b2) { + return !CheckStringInContact.checkInContact(b1, b2); + } +} diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/StringBoundary.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/StringBoundary.java index 1aa866d510b6a205a546d74857b669da687028f3..762744e0ecf05a676854e15a6ceecafe8f710982 100644 --- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/StringBoundary.java +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/StringBoundary.java @@ -5,7 +5,7 @@ import de.unikoblenz.fgbks.base.utils.boundary.Boundary; import de.unikoblenz.fgbks.base.utils.boundary.BoundaryParseException; import de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheck; import de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType; -import de.unikoblenz.fgbks.base.utils.boundary.checker.CheckEqualString; +import de.unikoblenz.fgbks.base.utils.boundary.checker.CheckStringEqual; import java.util.Arrays; import java.util.HashMap; import java.util.Objects; @@ -16,6 +16,7 @@ public class StringBoundary extends AbstractBoundary<String> { private boolean matchNoneOfValues; private boolean matchAny; private String[] values; + // sorted list of cached hashes of valuesHashes private int[] valuesHashes; public StringBoundary(String text) { @@ -55,6 +56,7 @@ public class StringBoundary extends AbstractBoundary<String> { matchAny = Validate.notNull(text).isEmpty(); if (matchAny) { values = new String[0]; + valuesHashes = new int[0]; } else { matchNoneOfValues = text.toLowerCase().startsWith("not"); text = text.replace('(', '\0').replace(')', '\0').trim(); @@ -83,7 +85,7 @@ public class StringBoundary extends AbstractBoundary<String> { @Override protected HashMap<BoundaryCheckType, BoundaryCheck> getChecker() { HashMap<BoundaryCheckType, BoundaryCheck> map = new HashMap<>(); - map.put(BoundaryCheckType.IS_EQUAL, CheckEqualString.getInstance()); + map.put(BoundaryCheckType.IS_EQUAL, CheckStringEqual.getInstance()); return map; } diff --git a/dmnverifierapi/src/test/java/de/unikoblenz/fgbks/base/utils/boundary/checker/AbstractStringCheckerTest.java b/dmnverifierapi/src/test/java/de/unikoblenz/fgbks/base/utils/boundary/checker/AbstractStringCheckerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..18cd2b2afc2a1dd630f0b491059f14cb28c71e41 --- /dev/null +++ b/dmnverifierapi/src/test/java/de/unikoblenz/fgbks/base/utils/boundary/checker/AbstractStringCheckerTest.java @@ -0,0 +1,34 @@ +package de.unikoblenz.fgbks.base.utils.boundary.checker; + +import static de.unikoblenz.fgbks.core.dmn.domain.vdmn.VTypeRef.STRING; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import de.unikoblenz.fgbks.base.utils.boundary.Boundary; +import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VTypeRef; + +public abstract class AbstractStringCheckerTest { + + protected BoundaryCheck checker; + + protected void doStringCheck(String b1, String b2, boolean expected) { + doCheck(STRING, b1, b2, expected); + if (checkBothWays()) { + doCheck(STRING, b2, b1, expected); + } + } + + private void doCheck(VTypeRef type, String b1, String b2, boolean expected) { + doCheck(type.getBoundaryFromText(b1).get(), type.getBoundaryFromText(b2).get(), expected); + } + + private void doCheck(Boundary b1, Boundary b2, boolean expected) { + if (expected) { + assertTrue(checker.check(b1, b2), b1.getText() + " / " + b2.getText()); + } else { + assertFalse(checker.check(b1, b2), b1.getText() + " / " + b2.getText()); + } + } + + protected abstract boolean checkBothWays(); +} diff --git a/dmnverifierapi/src/test/java/de/unikoblenz/fgbks/base/utils/boundary/checker/CheckStringInContactTest.java b/dmnverifierapi/src/test/java/de/unikoblenz/fgbks/base/utils/boundary/checker/CheckStringInContactTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0e4bddcd2cc067c1fcfdfa4a500bf6bbcf9153c8 --- /dev/null +++ b/dmnverifierapi/src/test/java/de/unikoblenz/fgbks/base/utils/boundary/checker/CheckStringInContactTest.java @@ -0,0 +1,30 @@ +package de.unikoblenz.fgbks.base.utils.boundary.checker; + +import io.quarkus.test.junit.QuarkusTest; +import org.junit.jupiter.api.Test; + +@QuarkusTest +class CheckStringInContactTest extends AbstractStringCheckerTest { + + @Test + void check() { + super.checker = CheckStringInContact.getInstance(); + doStringCheck("\"a\"", "\"a\"", true); + doStringCheck("\"a\"", "\"b\"", false); + doStringCheck("\"a\"", "not(\"a\")", false); + doStringCheck("\"a\"", "not(\"b\")", true); + doStringCheck("\"a\"", "\"a\",\"b\"", true); + doStringCheck("\"a\"", "\"c\",\"b\"", false); + doStringCheck("\"a\"", "not(\"a\",\"b\")", true); + doStringCheck("\"a\"", "not(\"c\",\"b\")", true); + doStringCheck("", "not(\"c\",\"b\")", true); + doStringCheck("", "\"c\",\"b\"", true); + doStringCheck("", "\"c\"", true); + doStringCheck("", "", true); + } + + @Override + protected boolean checkBothWays() { + return true; + } +} diff --git a/dmnverifierapi/src/test/java/de/unikoblenz/fgbks/base/utils/boundary/checker/CheckStringNotInContactTest.java b/dmnverifierapi/src/test/java/de/unikoblenz/fgbks/base/utils/boundary/checker/CheckStringNotInContactTest.java new file mode 100644 index 0000000000000000000000000000000000000000..5ead66854672bc4f8ce78cab080f156bba66738a --- /dev/null +++ b/dmnverifierapi/src/test/java/de/unikoblenz/fgbks/base/utils/boundary/checker/CheckStringNotInContactTest.java @@ -0,0 +1,26 @@ +package de.unikoblenz.fgbks.base.utils.boundary.checker; + +import io.quarkus.test.junit.QuarkusTest; +import org.junit.jupiter.api.Test; + +@QuarkusTest +class CheckStringNotInContactTest extends AbstractStringCheckerTest { + + @Test + void check() { + super.checker = CheckStringNotContact.getInstance(); + doStringCheck("\"a\"", "\"a\"", false); + doStringCheck("\"a\"", "\"b\"", true); + doStringCheck("\"a\"", "not(\"a\")", true); + doStringCheck("\"a\"", "not(\"b\")", false); + doStringCheck("\"a\"", "\"a\",\"b\"", false); + doStringCheck("\"a\"", "\"c\",\"b\"", true); + doStringCheck("\"a\"", "not(\"a\",\"b\")", false); + doStringCheck("\"a\"", "not(\"c\",\"b\")", false); + } + + @Override + protected boolean checkBothWays() { + return true; + } +}