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;
+  }
+}