From d1fd2745fa7e4f14de5ff0f46f55212abe60b4c0 Mon Sep 17 00:00:00 2001
From: Jonas Blatt <jonasblatt@uni-koblenz.de>
Date: Mon, 23 Sep 2019 20:45:44 +0200
Subject: [PATCH] Add creater for boundaries

---
 .../base/utils/boundary/AbstractBoundary.java | 34 ++++---
 .../boundary/AbstractGrowingBoundary.java     | 83 +++++++++-------
 .../fgbks/base/utils/boundary/Boundary.java   |  4 +-
 .../bicreater/AbstractBoundaryBiCreater.java  |  6 ++
 .../boundary/bicreater/BiCreaterAppend.java   | 97 +++++++++++++++++++
 .../boundary/bicreater/BiCreaterBetween.java  | 72 ++++++++++++++
 .../boundary/bicreater/BiCreaterCombine.java  | 51 ++++++++++
 .../boundary/bicreater/BoundaryBiCreater.java | 11 +++
 .../bicreater/BoundaryBiCreaterType.java      | 10 ++
 .../boundary/bicreater/EmptyBiCreater.java    | 27 ++++++
 .../combiner/AbstractBoundaryCombiner.java    |  5 -
 .../combiner/BoundaryCombineType.java         | 10 --
 .../boundary/combiner/BoundaryCombiner.java   | 11 ---
 .../boundary/combiner/EmptyCombiner.java      | 27 ------
 .../utils/boundary/creater/CreaterLower.java  | 36 +++++++
 .../utils/boundary/creater/CreaterUpper.java  | 36 +++++++
 .../utils/boundary/impl/BooleanBoundary.java  | 21 +++-
 .../utils/boundary/impl/DateBoundary.java     | 24 ++++-
 .../utils/boundary/impl/DoubleBoundary.java   | 21 +++-
 .../utils/boundary/impl/IntegerBoundary.java  | 22 ++++-
 .../utils/boundary/impl/InvalidBoundary.java  |  4 +-
 .../utils/boundary/impl/LongBoundary.java     | 22 ++++-
 .../utils/boundary/impl/StringBoundary.java   | 73 ++++++++------
 23 files changed, 560 insertions(+), 147 deletions(-)
 create mode 100644 dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/AbstractBoundaryBiCreater.java
 create mode 100644 dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/BiCreaterAppend.java
 create mode 100644 dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/BiCreaterBetween.java
 create mode 100644 dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/BiCreaterCombine.java
 create mode 100644 dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/BoundaryBiCreater.java
 create mode 100644 dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/BoundaryBiCreaterType.java
 create mode 100644 dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/EmptyBiCreater.java
 delete mode 100644 dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/combiner/AbstractBoundaryCombiner.java
 delete mode 100644 dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/combiner/BoundaryCombineType.java
 delete mode 100644 dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/combiner/BoundaryCombiner.java
 delete mode 100644 dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/combiner/EmptyCombiner.java
 create mode 100644 dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/creater/CreaterLower.java
 create mode 100644 dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/creater/CreaterUpper.java

diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/AbstractBoundary.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/AbstractBoundary.java
index 13e97a2d..8883fe32 100644
--- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/AbstractBoundary.java
+++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/AbstractBoundary.java
@@ -1,9 +1,9 @@
 package de.unikoblenz.fgbks.base.utils.boundary;
 
+import de.unikoblenz.fgbks.base.utils.boundary.bicreater.BoundaryBiCreater;
+import de.unikoblenz.fgbks.base.utils.boundary.bicreater.BoundaryBiCreaterType;
 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.combiner.BoundaryCombineType;
-import de.unikoblenz.fgbks.base.utils.boundary.combiner.BoundaryCombiner;
 import de.unikoblenz.fgbks.base.utils.boundary.creater.BoundaryCreater;
 import de.unikoblenz.fgbks.base.utils.boundary.creater.BoundaryCreaterType;
 import de.unikoblenz.fgbks.base.utils.boundary.impl.InvalidBoundary;
@@ -15,21 +15,25 @@ import org.apache.commons.lang3.Validate;
 public abstract class AbstractBoundary<T extends Comparable<? super T>> implements Boundary {
 
   private HashMap<BoundaryCheckType, BoundaryCheck> checkFunctions;
-  private HashMap<BoundaryCombineType, BoundaryCombiner> combineFunctions;
+  private HashMap<BoundaryBiCreaterType, BoundaryBiCreater> biCreaterFunctions;
   private HashMap<BoundaryCreaterType, BoundaryCreater> createrFunctions;
   private Class<T> type;
   private String text;
 
-  public AbstractBoundary(String text, Class<T> type) {
+  protected AbstractBoundary(String text, Class<T> type) {
     this.text = text;
     this.type = type;
     parse(text);
     validate();
     checkFunctions = new HashMap<>(getChecker());
-    combineFunctions = new HashMap<>(getCombiner());
+    biCreaterFunctions = new HashMap<>(getBiCreater());
     createrFunctions = new HashMap<>(getCreater());
   }
 
+  protected AbstractBoundary(Class<T> type) {
+    this("", type);
+  }
+
   @Override
   public String getText() {
     return text;
@@ -62,15 +66,15 @@ public abstract class AbstractBoundary<T extends Comparable<? super T>> implemen
   }
 
   @Override
-  public Optional<Boundary> combine(BoundaryCombineType combineType, Boundary other) {
+  public Optional<Boundary> createBi(BoundaryBiCreaterType combineType, Boundary other) {
     if (other instanceof InvalidBoundary) {
       return Optional.empty();
     }
-    BoundaryCombiner combiner = getCombineFunction(combineType);
-    if (combiner == null || !isValidOperation(combineType, other)) {
+    BoundaryBiCreater biCreater = getBiCreaterFunction(combineType);
+    if (biCreater == null || !isValidOperation(combineType, other)) {
       throw new BoundaryOperationNotSupportedException(); // TODO: add error text
     }
-    return combiner.combine(this, other); // TODO, remove RAW type
+    return biCreater.create(this, other); // TODO, remove RAW type
   }
 
   public boolean isValidOperation(BoundaryCheckType checkType, Boundary other) {
@@ -81,12 +85,12 @@ public abstract class AbstractBoundary<T extends Comparable<? super T>> implemen
     return checkFunctions.containsKey(Validate.notNull(checkType));
   }
 
-  public boolean isValidOperation(BoundaryCombineType combineType, Boundary other) {
+  public boolean isValidOperation(BoundaryBiCreaterType combineType, Boundary other) {
     return this.getTypeRef() == other.getTypeRef() && isValidOperation(combineType);
   }
 
-  public boolean isValidOperation(BoundaryCombineType combineTyp) {
-    return combineFunctions.containsKey(Validate.notNull(combineTyp));
+  public boolean isValidOperation(BoundaryBiCreaterType combineTyp) {
+    return biCreaterFunctions.containsKey(Validate.notNull(combineTyp));
   }
 
   public boolean isValidOperation(BoundaryCreaterType createrType) {
@@ -101,8 +105,8 @@ public abstract class AbstractBoundary<T extends Comparable<? super T>> implemen
     return createrFunctions.get(createrType);
   }
 
-  protected BoundaryCombiner getCombineFunction(BoundaryCombineType combineTypeType) {
-    return combineFunctions.get(combineTypeType);
+  protected BoundaryBiCreater getBiCreaterFunction(BoundaryBiCreaterType biCreaterTypeType) {
+    return biCreaterFunctions.get(biCreaterTypeType);
   }
 
   protected abstract void parse(String text);
@@ -111,7 +115,7 @@ public abstract class AbstractBoundary<T extends Comparable<? super T>> implemen
 
   protected abstract HashMap<BoundaryCheckType, BoundaryCheck> getChecker();
 
-  protected abstract HashMap<BoundaryCombineType, BoundaryCombiner> getCombiner();
+  protected abstract HashMap<BoundaryBiCreaterType, BoundaryBiCreater> getBiCreater();
 
   protected abstract HashMap<BoundaryCreaterType, BoundaryCreater> getCreater();
 
diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/AbstractGrowingBoundary.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/AbstractGrowingBoundary.java
index 07c4709b..a64b1091 100644
--- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/AbstractGrowingBoundary.java
+++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/AbstractGrowingBoundary.java
@@ -1,21 +1,27 @@
 package de.unikoblenz.fgbks.base.utils.boundary;
 
 import static de.unikoblenz.fgbks.base.utils.boundary.BoundType.INCLUSIVE;
+import static de.unikoblenz.fgbks.base.utils.boundary.bicreater.BoundaryBiCreaterType.APPEND;
+import static de.unikoblenz.fgbks.base.utils.boundary.bicreater.BoundaryBiCreaterType.BETWEEN;
+import static de.unikoblenz.fgbks.base.utils.boundary.bicreater.BoundaryBiCreaterType.COMBINE;
+import static de.unikoblenz.fgbks.base.utils.boundary.bicreater.BoundaryBiCreaterType.INTERSECTION;
+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_IN_CONTACT;
 import static de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType.IS_NOT_IN_CONTACT;
 import static de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType.IS_OVERLAPPING;
 import static de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType.IS_SUBSUMPTION;
 import static de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType.SUBSUMES;
-import static de.unikoblenz.fgbks.base.utils.boundary.combiner.BoundaryCombineType.APPEND;
-import static de.unikoblenz.fgbks.base.utils.boundary.combiner.BoundaryCombineType.BETWEEN;
-import static de.unikoblenz.fgbks.base.utils.boundary.combiner.BoundaryCombineType.COMBINE;
-import static de.unikoblenz.fgbks.base.utils.boundary.combiner.BoundaryCombineType.INTERSECTION;
-import static de.unikoblenz.fgbks.base.utils.boundary.combiner.BoundaryCombineType.LOWER_BOUNDS;
-import static de.unikoblenz.fgbks.base.utils.boundary.combiner.BoundaryCombineType.UPPER_BOUNDS;
 import static de.unikoblenz.fgbks.base.utils.boundary.creater.BoundaryCreaterType.LOWER;
 import static de.unikoblenz.fgbks.base.utils.boundary.creater.BoundaryCreaterType.UPPER;
 
+import de.unikoblenz.fgbks.base.utils.boundary.bicreater.BiCreaterAppend;
+import de.unikoblenz.fgbks.base.utils.boundary.bicreater.BiCreaterBetween;
+import de.unikoblenz.fgbks.base.utils.boundary.bicreater.BiCreaterCombine;
+import de.unikoblenz.fgbks.base.utils.boundary.bicreater.BoundaryBiCreater;
+import de.unikoblenz.fgbks.base.utils.boundary.bicreater.BoundaryBiCreaterType;
+import de.unikoblenz.fgbks.base.utils.boundary.bicreater.EmptyBiCreater;
 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.CheckEqual;
@@ -24,12 +30,10 @@ import de.unikoblenz.fgbks.base.utils.boundary.checker.CheckIsSubsumption;
 import de.unikoblenz.fgbks.base.utils.boundary.checker.CheckNotInContact;
 import de.unikoblenz.fgbks.base.utils.boundary.checker.CheckOverlap;
 import de.unikoblenz.fgbks.base.utils.boundary.checker.CheckSubsumes;
-import de.unikoblenz.fgbks.base.utils.boundary.combiner.BoundaryCombineType;
-import de.unikoblenz.fgbks.base.utils.boundary.combiner.BoundaryCombiner;
-import de.unikoblenz.fgbks.base.utils.boundary.combiner.EmptyCombiner;
 import de.unikoblenz.fgbks.base.utils.boundary.creater.BoundaryCreater;
 import de.unikoblenz.fgbks.base.utils.boundary.creater.BoundaryCreaterType;
-import de.unikoblenz.fgbks.base.utils.boundary.creater.EmptyCreater;
+import de.unikoblenz.fgbks.base.utils.boundary.creater.CreaterLower;
+import de.unikoblenz.fgbks.base.utils.boundary.creater.CreaterUpper;
 import java.util.HashMap;
 import java.util.Objects;
 import org.apache.commons.lang3.Validate;
@@ -37,6 +41,27 @@ import org.apache.commons.lang3.Validate;
 public abstract class AbstractGrowingBoundary<T extends Comparable<? super T>>
     extends AbstractBoundary<T> {
 
+  private static HashMap<BoundaryCheckType, BoundaryCheck> checkerMap = new HashMap<>();
+  private static HashMap<BoundaryCreaterType, BoundaryCreater> createrMap = new HashMap<>();
+  private static HashMap<BoundaryBiCreaterType, BoundaryBiCreater> biCreaterMap = new HashMap<>();
+
+  static {
+    checkerMap.put(IS_EQUAL, CheckEqual.getInstance());
+    checkerMap.put(IS_IN_CONTACT, CheckInContact.getInstance());
+    checkerMap.put(IS_NOT_IN_CONTACT, CheckNotInContact.getInstance());
+    checkerMap.put(IS_OVERLAPPING, CheckOverlap.getInstance());
+    checkerMap.put(IS_SUBSUMPTION, CheckIsSubsumption.getInstance());
+    checkerMap.put(SUBSUMES, CheckSubsumes.getInstance());
+    createrMap.put(UPPER, CreaterUpper.getInstance());
+    createrMap.put(LOWER, CreaterLower.getInstance());
+    biCreaterMap.put(INTERSECTION, EmptyBiCreater.getInstance());
+    biCreaterMap.put(LOWER_BOUNDS, EmptyBiCreater.getInstance());
+    biCreaterMap.put(UPPER_BOUNDS, EmptyBiCreater.getInstance());
+    biCreaterMap.put(BETWEEN, BiCreaterBetween.getInstance());
+    biCreaterMap.put(APPEND, BiCreaterAppend.getInstance());
+    biCreaterMap.put(COMBINE, BiCreaterCombine.getInstance());
+  }
+
   protected T lowerBound;
   protected BoundType lowerBoundType;
   protected T upperBound;
@@ -58,10 +83,14 @@ public abstract class AbstractGrowingBoundary<T extends Comparable<? super T>>
     return upperBoundType;
   }
 
-  public AbstractGrowingBoundary(String text, Class<T> type) {
+  protected AbstractGrowingBoundary(String text, Class<T> type) {
     super(text, type);
   }
 
+  protected AbstractGrowingBoundary(Class<T> type) {
+    super(type);
+  }
+
   @Override
   protected void validate() {
     Validate.notNull(lowerBound);
@@ -87,34 +116,17 @@ public abstract class AbstractGrowingBoundary<T extends Comparable<? super T>>
 
   @Override
   protected HashMap<BoundaryCheckType, BoundaryCheck> getChecker() {
-    HashMap<BoundaryCheckType, BoundaryCheck> map = new HashMap<>();
-    map.put(IS_EQUAL, CheckEqual.getInstance());
-    map.put(IS_IN_CONTACT, CheckInContact.getInstance());
-    map.put(IS_NOT_IN_CONTACT, CheckNotInContact.getInstance());
-    map.put(IS_OVERLAPPING, CheckOverlap.getInstance());
-    map.put(IS_SUBSUMPTION, CheckIsSubsumption.getInstance());
-    map.put(SUBSUMES, CheckSubsumes.getInstance());
-    return map;
+    return checkerMap;
   }
 
   @Override
-  protected HashMap<BoundaryCombineType, BoundaryCombiner> getCombiner() {
-    HashMap<BoundaryCombineType, BoundaryCombiner> map = new HashMap<>();
-    map.put(INTERSECTION, EmptyCombiner.getInstance());
-    map.put(LOWER_BOUNDS, EmptyCombiner.getInstance());
-    map.put(UPPER_BOUNDS, EmptyCombiner.getInstance());
-    map.put(BETWEEN, EmptyCombiner.getInstance());
-    map.put(APPEND, EmptyCombiner.getInstance());
-    map.put(COMBINE, EmptyCombiner.getInstance());
-    return map;
+  protected HashMap<BoundaryBiCreaterType, BoundaryBiCreater> getBiCreater() {
+    return biCreaterMap;
   }
 
   @Override
   protected HashMap<BoundaryCreaterType, BoundaryCreater> getCreater() {
-    HashMap<BoundaryCreaterType, BoundaryCreater> map = new HashMap<>();
-    map.put(UPPER, EmptyCreater.getInstance());
-    map.put(LOWER, EmptyCreater.getInstance());
-    return map;
+    return createrMap;
   }
 
   @Override
@@ -171,9 +183,12 @@ public abstract class AbstractGrowingBoundary<T extends Comparable<? super T>>
     return upperBound.compareTo((T) o.upperBound);
   }
 
-  protected abstract T getMinValue();
+  public abstract T getMinValue();
+
+  public abstract T getMaxValue();
 
-  protected abstract T getMaxValue();
+  public abstract AbstractGrowingBoundary getCopy(
+      T lowerBound, T upperBound, BoundType lowerBoundType, BoundType upperBoundType);
 
   @Override
   protected String getParsedText() {
diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/Boundary.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/Boundary.java
index fab3d6b1..7772b3d8 100644
--- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/Boundary.java
+++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/Boundary.java
@@ -1,7 +1,7 @@
 package de.unikoblenz.fgbks.base.utils.boundary;
 
+import de.unikoblenz.fgbks.base.utils.boundary.bicreater.BoundaryBiCreaterType;
 import de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType;
-import de.unikoblenz.fgbks.base.utils.boundary.combiner.BoundaryCombineType;
 import de.unikoblenz.fgbks.base.utils.boundary.creater.BoundaryCreaterType;
 import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VTypeRef;
 import java.util.Optional;
@@ -16,5 +16,5 @@ public interface Boundary extends Comparable<Boundary> {
 
   Optional<Boundary> create(BoundaryCreaterType createType);
 
-  Optional<Boundary> combine(BoundaryCombineType combineType, Boundary other);
+  Optional<Boundary> createBi(BoundaryBiCreaterType combineType, Boundary other);
 }
diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/AbstractBoundaryBiCreater.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/AbstractBoundaryBiCreater.java
new file mode 100644
index 00000000..85c0664c
--- /dev/null
+++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/AbstractBoundaryBiCreater.java
@@ -0,0 +1,6 @@
+package de.unikoblenz.fgbks.base.utils.boundary.bicreater;
+
+import de.unikoblenz.fgbks.base.utils.boundary.Boundary;
+
+public abstract class AbstractBoundaryBiCreater<T extends Boundary>
+    implements BoundaryBiCreater<T> {}
diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/BiCreaterAppend.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/BiCreaterAppend.java
new file mode 100644
index 00000000..1be74c3b
--- /dev/null
+++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/BiCreaterAppend.java
@@ -0,0 +1,97 @@
+package de.unikoblenz.fgbks.base.utils.boundary.bicreater;
+
+import static de.unikoblenz.fgbks.base.utils.boundary.BoundType.INCLUSIVE;
+import static de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType.IS_NOT_IN_CONTACT;
+
+import de.unikoblenz.fgbks.base.utils.boundary.AbstractGrowingBoundary;
+import de.unikoblenz.fgbks.base.utils.boundary.impl.BooleanBoundary;
+import de.unikoblenz.fgbks.base.utils.boundary.impl.IntegerBoundary;
+import de.unikoblenz.fgbks.base.utils.boundary.impl.LongBoundary;
+import java.util.Optional;
+
+public class BiCreaterAppend extends AbstractBoundaryBiCreater<AbstractGrowingBoundary> {
+
+  private static final BiCreaterAppend instance = new BiCreaterAppend();
+
+  private BiCreaterAppend() {
+    super();
+  }
+
+  public static BiCreaterAppend getInstance() {
+    return instance;
+  }
+
+  @Override
+  public BoundaryBiCreaterType getType() {
+    return BoundaryBiCreaterType.APPEND;
+  }
+
+  @Override
+  public Optional<AbstractGrowingBoundary> create(
+      AbstractGrowingBoundary b1, AbstractGrowingBoundary b2) {
+    if (b1.checkWith(IS_NOT_IN_CONTACT, b2)) {
+      if (b1 instanceof BooleanBoundary) {
+        return createrBoolean((BooleanBoundary) b1, (BooleanBoundary) b2);
+      }
+      if (b1 instanceof IntegerBoundary || b1 instanceof LongBoundary) {
+        return createrLong(b1, b2);
+      }
+      if (b1.getUpperBound().equals(b2.getLowerBound())
+          && b1.getUpperBoundType() != b2.getLowerBoundType()) {
+        return Optional.of(
+            b1.getCopy(
+                b1.getLowerBound(),
+                b2.getUpperBound(),
+                b1.getLowerBoundType(),
+                b2.getUpperBoundType()));
+      } else if (b2.getUpperBound().equals(b1.getLowerBound())
+          && b2.getUpperBoundType() != b1.getLowerBoundType()) {
+        return Optional.of(
+            b1.getCopy(
+                b2.getLowerBound(),
+                b1.getUpperBound(),
+                b2.getLowerBoundType(),
+                b1.getUpperBoundType()));
+      }
+    }
+    return Optional.empty();
+  }
+
+  private Optional<AbstractGrowingBoundary> createrLong(
+      AbstractGrowingBoundary b1, AbstractGrowingBoundary b2) {
+    long b1L = (long) b1.getLowerBound();
+    long b1U = (long) b1.getUpperBound();
+    long b2L = (long) b1.getLowerBound();
+    long b2U = (long) b1.getUpperBound();
+    if (b1U + 1 == b2L
+        && b1.getUpperBoundType() == INCLUSIVE
+        && b2.getLowerBoundType() == INCLUSIVE) {
+      return Optional.of(
+          b1.getCopy(
+              b1.getLowerBound(),
+              b2.getUpperBound(),
+              b1.getLowerBoundType(),
+              b2.getUpperBoundType()));
+    } else if (b2U + 1 == b1L
+        && b2.getUpperBoundType() == INCLUSIVE
+        && b1.getLowerBoundType() == INCLUSIVE) {
+      return Optional.of(
+          b1.getCopy(
+              b2.getLowerBound(),
+              b1.getUpperBound(),
+              b2.getLowerBoundType(),
+              b1.getUpperBoundType()));
+    }
+    return Optional.empty();
+  }
+
+  private Optional<AbstractGrowingBoundary> createrBoolean(BooleanBoundary b1, BooleanBoundary b2) {
+    if ((b1.getLowerBound() == b1.getUpperBound())
+        && (b2.getLowerBound() == b2.getUpperBound())
+        && b1.getLowerBound() != b1.getLowerBound()) {
+      return Optional.of(new BooleanBoundary(""));
+    } else {
+      return Optional.empty();
+    }
+  }
+}
diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/BiCreaterBetween.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/BiCreaterBetween.java
new file mode 100644
index 00000000..3c9f40a3
--- /dev/null
+++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/BiCreaterBetween.java
@@ -0,0 +1,72 @@
+package de.unikoblenz.fgbks.base.utils.boundary.bicreater;
+
+import static de.unikoblenz.fgbks.base.utils.boundary.BoundType.INCLUSIVE;
+
+import de.unikoblenz.fgbks.base.utils.boundary.AbstractGrowingBoundary;
+import de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType;
+import de.unikoblenz.fgbks.base.utils.boundary.impl.BooleanBoundary;
+import de.unikoblenz.fgbks.base.utils.boundary.impl.DoubleBoundary;
+import de.unikoblenz.fgbks.base.utils.boundary.impl.IntegerBoundary;
+import java.util.Optional;
+
+public class BiCreaterBetween extends AbstractBoundaryBiCreater<AbstractGrowingBoundary> {
+
+  private static final BiCreaterBetween instance = new BiCreaterBetween();
+
+  private BiCreaterBetween() {
+    super();
+  }
+
+  public static BiCreaterBetween getInstance() {
+    return instance;
+  }
+
+  @Override
+  public BoundaryBiCreaterType getType() {
+    return BoundaryBiCreaterType.BETWEEN;
+  }
+
+  @Override
+  public Optional<AbstractGrowingBoundary> create(
+      AbstractGrowingBoundary b1, AbstractGrowingBoundary b2) {
+    if (b1 instanceof BooleanBoundary || b1.checkWith(BoundaryCheckType.IS_IN_CONTACT, b2)) {
+      return Optional.empty();
+    }
+    // no space between the two bounds
+    if (b1.getUpperBound().equals(b2.getLowerBound())
+            && !b1.getUpperBound().equals(b2.getLowerBound())
+        || b2.getUpperBound().equals(b1.getLowerBound())
+            && !b2.getUpperBound().equals(b1.getLowerBound())) {
+      return Optional.empty();
+    }
+    if (b1 instanceof DoubleBoundary || b1 instanceof IntegerBoundary) {
+      long b1L = (long) b1.getLowerBound();
+      long b1U = (long) b1.getUpperBound();
+      long b2L = (long) b1.getLowerBound();
+      long b2U = (long) b1.getUpperBound();
+      if (b1U + 1 == b2L
+              && b1.getUpperBoundType() == INCLUSIVE
+              && b2.getLowerBoundType() == INCLUSIVE
+          || b2U + 1 == b1L
+              && b2.getUpperBoundType() == INCLUSIVE
+              && b1.getLowerBoundType() == INCLUSIVE) {
+        return Optional.empty();
+      }
+    }
+    if (b1.getLowerBound().compareTo(b2.getUpperBound()) < 0) {
+      return Optional.of(
+          b1.getCopy(
+              b1.getLowerBound(),
+              b2.getLowerBound(),
+              b1.getUpperBoundType().getOp(),
+              b2.getLowerBoundType().getOp()));
+    } else {
+      return Optional.of(
+          b1.getCopy(
+              b2.getLowerBound(),
+              b1.getLowerBound(),
+              b2.getUpperBoundType().getOp(),
+              b1.getLowerBoundType().getOp()));
+    }
+  }
+}
diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/BiCreaterCombine.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/BiCreaterCombine.java
new file mode 100644
index 00000000..303e7e8e
--- /dev/null
+++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/BiCreaterCombine.java
@@ -0,0 +1,51 @@
+package de.unikoblenz.fgbks.base.utils.boundary.bicreater;
+
+import static de.unikoblenz.fgbks.base.utils.boundary.BoundType.EXCLUSIVE;
+import static de.unikoblenz.fgbks.base.utils.boundary.BoundType.INCLUSIVE;
+import static de.unikoblenz.fgbks.base.utils.boundary.bicreater.BoundaryBiCreaterType.APPEND;
+import static de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType.IS_NOT_IN_CONTACT;
+
+import de.unikoblenz.fgbks.base.utils.boundary.AbstractGrowingBoundary;
+import java.util.Optional;
+
+public class BiCreaterCombine extends AbstractBoundaryBiCreater<AbstractGrowingBoundary> {
+
+  private static final BiCreaterCombine instance = new BiCreaterCombine();
+
+  private BiCreaterCombine() {
+    super();
+  }
+
+  public static BiCreaterCombine getInstance() {
+    return instance;
+  }
+
+  @Override
+  public BoundaryBiCreaterType getType() {
+    return APPEND;
+  }
+
+  @Override
+  public Optional<AbstractGrowingBoundary> create(
+      AbstractGrowingBoundary b1, AbstractGrowingBoundary b2) {
+    if (b1.checkWith(IS_NOT_IN_CONTACT, b2)) {
+      return b1.createBi(APPEND, b2);
+    }
+    int lC = b1.getLowerBound().compareTo(b2.getLowerBound());
+    int uC = b1.getUpperBound().compareTo(b2.getUpperBound());
+    return Optional.of(
+        b1.getCopy(
+            lC < 0 ? b1.getLowerBound() : b2.getLowerBound(),
+            uC > 0 ? b1.getUpperBound() : b2.getUpperBound(),
+            lC == 0
+                ? (b1.getLowerBoundType() == INCLUSIVE || b2.getLowerBoundType() == INCLUSIVE)
+                    ? INCLUSIVE
+                    : EXCLUSIVE
+                : lC < 0 ? b1.getLowerBoundType() : b2.getLowerBoundType(),
+            uC == 0
+                ? (b1.getUpperBoundType() == INCLUSIVE || b2.getUpperBoundType() == INCLUSIVE)
+                    ? INCLUSIVE
+                    : EXCLUSIVE
+                : lC > 0 ? b1.getUpperBoundType() : b2.getUpperBoundType()));
+  }
+}
diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/BoundaryBiCreater.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/BoundaryBiCreater.java
new file mode 100644
index 00000000..0a706080
--- /dev/null
+++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/BoundaryBiCreater.java
@@ -0,0 +1,11 @@
+package de.unikoblenz.fgbks.base.utils.boundary.bicreater;
+
+import de.unikoblenz.fgbks.base.utils.boundary.Boundary;
+import java.util.Optional;
+
+public interface BoundaryBiCreater<T extends Boundary> {
+
+  BoundaryBiCreaterType getType();
+
+  Optional<T> create(T b1, T b2);
+}
diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/BoundaryBiCreaterType.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/BoundaryBiCreaterType.java
new file mode 100644
index 00000000..60289a0e
--- /dev/null
+++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/BoundaryBiCreaterType.java
@@ -0,0 +1,10 @@
+package de.unikoblenz.fgbks.base.utils.boundary.bicreater;
+
+public enum BoundaryBiCreaterType {
+  INTERSECTION,
+  LOWER_BOUNDS,
+  UPPER_BOUNDS,
+  BETWEEN,
+  APPEND,
+  COMBINE;
+}
diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/EmptyBiCreater.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/EmptyBiCreater.java
new file mode 100644
index 00000000..e3251828
--- /dev/null
+++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/bicreater/EmptyBiCreater.java
@@ -0,0 +1,27 @@
+package de.unikoblenz.fgbks.base.utils.boundary.bicreater;
+
+import de.unikoblenz.fgbks.base.utils.boundary.Boundary;
+import java.util.Optional;
+
+public class EmptyBiCreater extends AbstractBoundaryBiCreater<Boundary> {
+
+  private static final EmptyBiCreater instance = new EmptyBiCreater();
+
+  private EmptyBiCreater() {
+    super();
+  }
+
+  public static EmptyBiCreater getInstance() {
+    return instance;
+  }
+
+  @Override
+  public BoundaryBiCreaterType getType() {
+    return null;
+  }
+
+  @Override
+  public Optional<Boundary> create(Boundary b1, Boundary b2) {
+    return Optional.empty();
+  }
+}
diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/combiner/AbstractBoundaryCombiner.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/combiner/AbstractBoundaryCombiner.java
deleted file mode 100644
index ed0cf6cb..00000000
--- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/combiner/AbstractBoundaryCombiner.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package de.unikoblenz.fgbks.base.utils.boundary.combiner;
-
-import de.unikoblenz.fgbks.base.utils.boundary.Boundary;
-
-public abstract class AbstractBoundaryCombiner<T extends Boundary> implements BoundaryCombiner<T> {}
diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/combiner/BoundaryCombineType.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/combiner/BoundaryCombineType.java
deleted file mode 100644
index bcfcb494..00000000
--- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/combiner/BoundaryCombineType.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package de.unikoblenz.fgbks.base.utils.boundary.combiner;
-
-public enum BoundaryCombineType {
-  INTERSECTION,
-  LOWER_BOUNDS,
-  UPPER_BOUNDS,
-  BETWEEN,
-  APPEND,
-  COMBINE;
-}
diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/combiner/BoundaryCombiner.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/combiner/BoundaryCombiner.java
deleted file mode 100644
index 10ce58c7..00000000
--- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/combiner/BoundaryCombiner.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package de.unikoblenz.fgbks.base.utils.boundary.combiner;
-
-import de.unikoblenz.fgbks.base.utils.boundary.Boundary;
-import java.util.Optional;
-
-public interface BoundaryCombiner<T extends Boundary> {
-
-  BoundaryCombineType getType();
-
-  Optional<T> combine(T b1, T b2);
-}
diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/combiner/EmptyCombiner.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/combiner/EmptyCombiner.java
deleted file mode 100644
index 7bea8da7..00000000
--- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/combiner/EmptyCombiner.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package de.unikoblenz.fgbks.base.utils.boundary.combiner;
-
-import de.unikoblenz.fgbks.base.utils.boundary.Boundary;
-import java.util.Optional;
-
-public class EmptyCombiner extends AbstractBoundaryCombiner<Boundary> {
-
-  private static final EmptyCombiner instance = new EmptyCombiner();
-
-  private EmptyCombiner() {
-    super();
-  }
-
-  public static EmptyCombiner getInstance() {
-    return instance;
-  }
-
-  @Override
-  public BoundaryCombineType getType() {
-    return null;
-  }
-
-  @Override
-  public Optional<Boundary> combine(Boundary b1, Boundary b2) {
-    return Optional.empty();
-  }
-}
diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/creater/CreaterLower.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/creater/CreaterLower.java
new file mode 100644
index 00000000..ce669e9f
--- /dev/null
+++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/creater/CreaterLower.java
@@ -0,0 +1,36 @@
+package de.unikoblenz.fgbks.base.utils.boundary.creater;
+
+import de.unikoblenz.fgbks.base.utils.boundary.AbstractGrowingBoundary;
+import de.unikoblenz.fgbks.base.utils.boundary.BoundType;
+import java.util.Optional;
+
+public class CreaterLower extends AbstractBoundaryCreater<AbstractGrowingBoundary> {
+
+  private static final CreaterLower instance = new CreaterLower();
+
+  private CreaterLower() {
+    super();
+  }
+
+  public static CreaterLower getInstance() {
+    return instance;
+  }
+
+  @Override
+  public BoundaryCreaterType getType() {
+    return BoundaryCreaterType.LOWER;
+  }
+
+  @Override
+  public Optional<AbstractGrowingBoundary> create(AbstractGrowingBoundary b) {
+    if (b.getLowerBound().equals(b.getMinValue())) {
+      return Optional.empty();
+    }
+    return Optional.of(
+        b.getCopy(
+            b.getMinValue(),
+            b.getLowerBound(),
+            BoundType.INCLUSIVE,
+            b.getLowerBoundType().getOp()));
+  }
+}
diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/creater/CreaterUpper.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/creater/CreaterUpper.java
new file mode 100644
index 00000000..8fe0b3ca
--- /dev/null
+++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/creater/CreaterUpper.java
@@ -0,0 +1,36 @@
+package de.unikoblenz.fgbks.base.utils.boundary.creater;
+
+import de.unikoblenz.fgbks.base.utils.boundary.AbstractGrowingBoundary;
+import de.unikoblenz.fgbks.base.utils.boundary.BoundType;
+import java.util.Optional;
+
+public class CreaterUpper extends AbstractBoundaryCreater<AbstractGrowingBoundary> {
+
+  private static final CreaterUpper instance = new CreaterUpper();
+
+  private CreaterUpper() {
+    super();
+  }
+
+  public static CreaterUpper getInstance() {
+    return instance;
+  }
+
+  @Override
+  public BoundaryCreaterType getType() {
+    return BoundaryCreaterType.UPPER;
+  }
+
+  @Override
+  public Optional<AbstractGrowingBoundary> create(AbstractGrowingBoundary b) {
+    if (b.getUpperBound().equals(b.getMaxValue())) {
+      return Optional.empty();
+    }
+    return Optional.of(
+        b.getCopy(
+            b.getUpperBound(),
+            b.getMaxValue(),
+            b.getUpperBoundType().getOp(),
+            BoundType.INCLUSIVE));
+  }
+}
diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/BooleanBoundary.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/BooleanBoundary.java
index b8ba1308..9d076692 100644
--- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/BooleanBoundary.java
+++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/BooleanBoundary.java
@@ -3,6 +3,7 @@ package de.unikoblenz.fgbks.base.utils.boundary.impl;
 import static de.unikoblenz.fgbks.base.utils.boundary.BoundType.INCLUSIVE;
 
 import de.unikoblenz.fgbks.base.utils.boundary.AbstractGrowingBoundary;
+import de.unikoblenz.fgbks.base.utils.boundary.BoundType;
 import de.unikoblenz.fgbks.base.utils.boundary.BoundaryParseException;
 
 public class BooleanBoundary extends AbstractGrowingBoundary<Boolean> {
@@ -14,16 +15,32 @@ public class BooleanBoundary extends AbstractGrowingBoundary<Boolean> {
     super(text, Boolean.TYPE);
   }
 
+  private BooleanBoundary() {
+    super(Boolean.TYPE);
+  }
+
   @Override
-  protected Boolean getMinValue() {
+  public Boolean getMinValue() {
     return false;
   }
 
   @Override
-  protected Boolean getMaxValue() {
+  public Boolean getMaxValue() {
     return true;
   }
 
+  @Override
+  public AbstractGrowingBoundary getCopy(
+      Boolean lowerBound, Boolean upperBound, BoundType lowerBoundType, BoundType upperBoundType) {
+    BooleanBoundary v = new BooleanBoundary();
+    v.lowerBound = lowerBound;
+    v.upperBound = upperBound;
+    v.lowerBoundType = lowerBoundType;
+    v.upperBoundType = upperBoundType;
+    v.validate();
+    return v;
+  }
+
   @Override
   protected void parse(String text) {
     upperBoundType = INCLUSIVE;
diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/DateBoundary.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/DateBoundary.java
index 3ffd379c..ef5b28d9 100644
--- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/DateBoundary.java
+++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/DateBoundary.java
@@ -4,6 +4,7 @@ import static de.unikoblenz.fgbks.base.utils.boundary.BoundType.EXCLUSIVE;
 import static de.unikoblenz.fgbks.base.utils.boundary.BoundType.INCLUSIVE;
 
 import de.unikoblenz.fgbks.base.utils.boundary.AbstractGrowingBoundary;
+import de.unikoblenz.fgbks.base.utils.boundary.BoundType;
 import de.unikoblenz.fgbks.base.utils.boundary.BoundaryParseException;
 import java.time.LocalDateTime;
 import java.util.regex.Matcher;
@@ -23,13 +24,32 @@ public class DateBoundary extends AbstractGrowingBoundary<LocalDateTime> {
     super(text, LocalDateTime.class);
   }
 
+  private DateBoundary() {
+    super(LocalDateTime.class);
+  }
+
+  @Override
+  public AbstractGrowingBoundary getCopy(
+      LocalDateTime lowerBound,
+      LocalDateTime upperBound,
+      BoundType lowerBoundType,
+      BoundType upperBoundType) {
+    DateBoundary v = new DateBoundary();
+    v.lowerBound = lowerBound;
+    v.upperBound = upperBound;
+    v.lowerBoundType = lowerBoundType;
+    v.upperBoundType = upperBoundType;
+    v.validate();
+    return v;
+  }
+
   @Override
-  protected LocalDateTime getMinValue() {
+  public LocalDateTime getMinValue() {
     return LocalDateTime.MAX;
   }
 
   @Override
-  protected LocalDateTime getMaxValue() {
+  public LocalDateTime getMaxValue() {
     return LocalDateTime.MIN;
   }
 
diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/DoubleBoundary.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/DoubleBoundary.java
index 3d1acde6..6dd52451 100644
--- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/DoubleBoundary.java
+++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/DoubleBoundary.java
@@ -4,6 +4,7 @@ import static de.unikoblenz.fgbks.base.utils.boundary.BoundType.EXCLUSIVE;
 import static de.unikoblenz.fgbks.base.utils.boundary.BoundType.INCLUSIVE;
 
 import de.unikoblenz.fgbks.base.utils.boundary.AbstractGrowingBoundary;
+import de.unikoblenz.fgbks.base.utils.boundary.BoundType;
 import de.unikoblenz.fgbks.base.utils.boundary.BoundaryParseException;
 import org.apache.commons.lang3.Validate;
 
@@ -13,13 +14,29 @@ public class DoubleBoundary extends AbstractGrowingBoundary<Double> {
     super(text, Double.TYPE);
   }
 
+  private DoubleBoundary() {
+    super(Double.TYPE);
+  }
+
+  @Override
+  public AbstractGrowingBoundary getCopy(
+      Double lowerBound, Double upperBound, BoundType lowerBoundType, BoundType upperBoundType) {
+    DoubleBoundary v = new DoubleBoundary();
+    v.lowerBound = lowerBound;
+    v.upperBound = upperBound;
+    v.lowerBoundType = lowerBoundType;
+    v.upperBoundType = upperBoundType;
+    v.validate();
+    return v;
+  }
+
   @Override
-  protected Double getMinValue() {
+  public Double getMinValue() {
     return Double.NEGATIVE_INFINITY;
   }
 
   @Override
-  protected Double getMaxValue() {
+  public Double getMaxValue() {
     return Double.POSITIVE_INFINITY;
   }
 
diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/IntegerBoundary.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/IntegerBoundary.java
index b2d5a790..79c53c50 100644
--- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/IntegerBoundary.java
+++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/IntegerBoundary.java
@@ -4,6 +4,7 @@ import static de.unikoblenz.fgbks.base.utils.boundary.BoundType.EXCLUSIVE;
 import static de.unikoblenz.fgbks.base.utils.boundary.BoundType.INCLUSIVE;
 
 import de.unikoblenz.fgbks.base.utils.boundary.AbstractGrowingBoundary;
+import de.unikoblenz.fgbks.base.utils.boundary.BoundType;
 import de.unikoblenz.fgbks.base.utils.boundary.BoundaryParseException;
 import org.apache.commons.lang3.Validate;
 
@@ -13,13 +14,30 @@ public class IntegerBoundary extends AbstractGrowingBoundary<Integer> {
     super(text, Integer.TYPE);
   }
 
+  private IntegerBoundary() {
+    super(Integer.TYPE);
+  }
+
+  @Override
+  public AbstractGrowingBoundary getCopy(
+      Integer lowerBound, Integer upperBound, BoundType lowerBoundType, BoundType upperBoundType) {
+    IntegerBoundary v = new IntegerBoundary();
+    v.lowerBound = lowerBound;
+    v.upperBound = upperBound;
+    v.lowerBoundType = lowerBoundType;
+    v.upperBoundType = upperBoundType;
+    v.simplifyBound();
+    v.validate();
+    return v;
+  }
+
   @Override
-  protected Integer getMinValue() {
+  public Integer getMinValue() {
     return Integer.MIN_VALUE;
   }
 
   @Override
-  protected Integer getMaxValue() {
+  public Integer getMaxValue() {
     return Integer.MAX_VALUE;
   }
 
diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/InvalidBoundary.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/InvalidBoundary.java
index 61b30aef..2523efd0 100644
--- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/InvalidBoundary.java
+++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/InvalidBoundary.java
@@ -1,8 +1,8 @@
 package de.unikoblenz.fgbks.base.utils.boundary.impl;
 
 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.base.utils.boundary.combiner.BoundaryCombineType;
 import de.unikoblenz.fgbks.base.utils.boundary.creater.BoundaryCreaterType;
 import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VTypeRef;
 import java.util.Optional;
@@ -38,7 +38,7 @@ public class InvalidBoundary implements Boundary {
   }
 
   @Override
-  public Optional<Boundary> combine(BoundaryCombineType combineType, Boundary other) {
+  public Optional<Boundary> createBi(BoundaryBiCreaterType combineType, Boundary other) {
     return Optional.empty();
   }
 
diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/LongBoundary.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/LongBoundary.java
index 162c0404..06e316d3 100644
--- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/LongBoundary.java
+++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/base/utils/boundary/impl/LongBoundary.java
@@ -4,6 +4,7 @@ import static de.unikoblenz.fgbks.base.utils.boundary.BoundType.EXCLUSIVE;
 import static de.unikoblenz.fgbks.base.utils.boundary.BoundType.INCLUSIVE;
 
 import de.unikoblenz.fgbks.base.utils.boundary.AbstractGrowingBoundary;
+import de.unikoblenz.fgbks.base.utils.boundary.BoundType;
 import de.unikoblenz.fgbks.base.utils.boundary.BoundaryParseException;
 import org.apache.commons.lang3.Validate;
 
@@ -13,13 +14,30 @@ public class LongBoundary extends AbstractGrowingBoundary<Long> {
     super(text, Long.TYPE);
   }
 
+  private LongBoundary() {
+    super(Long.TYPE);
+  }
+
+  @Override
+  public AbstractGrowingBoundary getCopy(
+      Long lowerBound, Long upperBound, BoundType lowerBoundType, BoundType upperBoundType) {
+    LongBoundary v = new LongBoundary();
+    v.lowerBound = lowerBound;
+    v.upperBound = upperBound;
+    v.lowerBoundType = lowerBoundType;
+    v.upperBoundType = upperBoundType;
+    v.simplifyBound();
+    v.validate();
+    return v;
+  }
+
   @Override
-  protected Long getMinValue() {
+  public Long getMinValue() {
     return Long.MIN_VALUE;
   }
 
   @Override
-  protected Long getMaxValue() {
+  public Long getMaxValue() {
     return Long.MAX_VALUE;
   }
 
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 d1eef32e..3f4540aa 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
@@ -1,17 +1,26 @@
 package de.unikoblenz.fgbks.base.utils.boundary.impl;
 
-import static de.unikoblenz.fgbks.base.utils.boundary.combiner.BoundaryCombineType.APPEND;
-import static de.unikoblenz.fgbks.base.utils.boundary.combiner.BoundaryCombineType.BETWEEN;
-import static de.unikoblenz.fgbks.base.utils.boundary.combiner.BoundaryCombineType.COMBINE;
-import static de.unikoblenz.fgbks.base.utils.boundary.combiner.BoundaryCombineType.INTERSECTION;
-import static de.unikoblenz.fgbks.base.utils.boundary.combiner.BoundaryCombineType.LOWER_BOUNDS;
-import static de.unikoblenz.fgbks.base.utils.boundary.combiner.BoundaryCombineType.UPPER_BOUNDS;
+import static de.unikoblenz.fgbks.base.utils.boundary.bicreater.BoundaryBiCreaterType.APPEND;
+import static de.unikoblenz.fgbks.base.utils.boundary.bicreater.BoundaryBiCreaterType.BETWEEN;
+import static de.unikoblenz.fgbks.base.utils.boundary.bicreater.BoundaryBiCreaterType.COMBINE;
+import static de.unikoblenz.fgbks.base.utils.boundary.bicreater.BoundaryBiCreaterType.INTERSECTION;
+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_IN_CONTACT;
+import static de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType.IS_NOT_IN_CONTACT;
+import static de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType.IS_OVERLAPPING;
+import static de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType.IS_SUBSUMPTION;
+import static de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType.SUBSUMES;
 import static de.unikoblenz.fgbks.base.utils.boundary.creater.BoundaryCreaterType.LOWER;
 import static de.unikoblenz.fgbks.base.utils.boundary.creater.BoundaryCreaterType.UPPER;
 
 import de.unikoblenz.fgbks.base.utils.boundary.AbstractBoundary;
 import de.unikoblenz.fgbks.base.utils.boundary.Boundary;
 import de.unikoblenz.fgbks.base.utils.boundary.BoundaryParseException;
+import de.unikoblenz.fgbks.base.utils.boundary.bicreater.BoundaryBiCreater;
+import de.unikoblenz.fgbks.base.utils.boundary.bicreater.BoundaryBiCreaterType;
+import de.unikoblenz.fgbks.base.utils.boundary.bicreater.EmptyBiCreater;
 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.CheckStringEqual;
@@ -20,12 +29,10 @@ import de.unikoblenz.fgbks.base.utils.boundary.checker.CheckStringNotInContact;
 import de.unikoblenz.fgbks.base.utils.boundary.checker.CheckStringOverlap;
 import de.unikoblenz.fgbks.base.utils.boundary.checker.CheckStringSubsumes;
 import de.unikoblenz.fgbks.base.utils.boundary.checker.CheckStringSubsumption;
-import de.unikoblenz.fgbks.base.utils.boundary.combiner.BoundaryCombineType;
-import de.unikoblenz.fgbks.base.utils.boundary.combiner.BoundaryCombiner;
-import de.unikoblenz.fgbks.base.utils.boundary.combiner.EmptyCombiner;
 import de.unikoblenz.fgbks.base.utils.boundary.creater.BoundaryCreater;
 import de.unikoblenz.fgbks.base.utils.boundary.creater.BoundaryCreaterType;
-import de.unikoblenz.fgbks.base.utils.boundary.creater.EmptyCreater;
+import de.unikoblenz.fgbks.base.utils.boundary.creater.CreaterLower;
+import de.unikoblenz.fgbks.base.utils.boundary.creater.CreaterUpper;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Objects;
@@ -33,6 +40,27 @@ import org.apache.commons.lang3.Validate;
 
 public class StringBoundary extends AbstractBoundary<String> {
 
+  private static HashMap<BoundaryCheckType, BoundaryCheck> checkerMap = new HashMap<>();
+  private static HashMap<BoundaryCreaterType, BoundaryCreater> createrMap = new HashMap<>();
+  private static HashMap<BoundaryBiCreaterType, BoundaryBiCreater> combinerMap = new HashMap<>();
+
+  static {
+    checkerMap.put(IS_EQUAL, CheckStringEqual.getInstance());
+    checkerMap.put(IS_IN_CONTACT, CheckStringInContact.getInstance());
+    checkerMap.put(IS_NOT_IN_CONTACT, CheckStringNotInContact.getInstance());
+    checkerMap.put(IS_OVERLAPPING, CheckStringOverlap.getInstance());
+    checkerMap.put(IS_SUBSUMPTION, CheckStringSubsumption.getInstance());
+    checkerMap.put(SUBSUMES, CheckStringSubsumes.getInstance());
+    createrMap.put(UPPER, CreaterUpper.getInstance());
+    createrMap.put(LOWER, CreaterLower.getInstance());
+    combinerMap.put(INTERSECTION, EmptyBiCreater.getInstance());
+    combinerMap.put(LOWER_BOUNDS, EmptyBiCreater.getInstance());
+    combinerMap.put(UPPER_BOUNDS, EmptyBiCreater.getInstance());
+    combinerMap.put(BETWEEN, EmptyBiCreater.getInstance());
+    combinerMap.put(APPEND, EmptyBiCreater.getInstance());
+    combinerMap.put(COMBINE, EmptyBiCreater.getInstance());
+  }
+
   private boolean matchNoneOfValues;
   private boolean matchAny;
   private String[] values;
@@ -104,34 +132,17 @@ public class StringBoundary extends AbstractBoundary<String> {
 
   @Override
   protected HashMap<BoundaryCheckType, BoundaryCheck> getChecker() {
-    HashMap<BoundaryCheckType, BoundaryCheck> map = new HashMap<>();
-    map.put(BoundaryCheckType.IS_EQUAL, CheckStringEqual.getInstance());
-    map.put(BoundaryCheckType.IS_IN_CONTACT, CheckStringInContact.getInstance());
-    map.put(BoundaryCheckType.IS_NOT_IN_CONTACT, CheckStringNotInContact.getInstance());
-    map.put(BoundaryCheckType.IS_OVERLAPPING, CheckStringOverlap.getInstance());
-    map.put(BoundaryCheckType.IS_SUBSUMPTION, CheckStringSubsumption.getInstance());
-    map.put(BoundaryCheckType.SUBSUMES, CheckStringSubsumes.getInstance());
-    return map;
+    return checkerMap;
   }
 
   @Override
-  protected HashMap<BoundaryCombineType, BoundaryCombiner> getCombiner() {
-    HashMap<BoundaryCombineType, BoundaryCombiner> map = new HashMap<>();
-    map.put(INTERSECTION, EmptyCombiner.getInstance());
-    map.put(LOWER_BOUNDS, EmptyCombiner.getInstance());
-    map.put(UPPER_BOUNDS, EmptyCombiner.getInstance());
-    map.put(BETWEEN, EmptyCombiner.getInstance());
-    map.put(APPEND, EmptyCombiner.getInstance());
-    map.put(COMBINE, EmptyCombiner.getInstance());
-    return map;
+  protected HashMap<BoundaryBiCreaterType, BoundaryBiCreater> getBiCreater() {
+    return combinerMap;
   }
 
   @Override
   protected HashMap<BoundaryCreaterType, BoundaryCreater> getCreater() {
-    HashMap<BoundaryCreaterType, BoundaryCreater> map = new HashMap<>();
-    map.put(UPPER, EmptyCreater.getInstance());
-    map.put(LOWER, EmptyCreater.getInstance());
-    return map;
+    return createrMap;
   }
 
   @Override
-- 
GitLab