diff --git a/dmn-generator/pom.xml b/dmn-generator/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ac43643f6e095dca61cf3534f04ae390ea50f44d
--- /dev/null
+++ b/dmn-generator/pom.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+       <modelVersion>4.0.0</modelVersion>
+
+    <groupId>de.unikoblenz.fgbks</groupId>
+    <artifactId>dmn-generator</artifactId>
+    <version>1.0-SNAPSHOT</version>
+    <name>DMN generator</name>
+    <packaging>jar</packaging>
+
+    <properties>
+        <!--Define versions for dependencies-->
+        <org.w3c.dom.version>2.3.0-jaxb-1.0.6</org.w3c.dom.version>
+    </properties>
+
+    <dependencies>
+        <!--DOM XML parser-->
+        <dependency>
+            <groupId>org.w3c</groupId>
+            <artifactId>dom</artifactId>
+            <version>${org.w3c.dom.version}</version>
+        </dependency>
+
+        <!--Backend application-->
+        <dependency>
+            <groupId>de.unikoblenz.fgbks</groupId>
+            <artifactId>dmn-verifier-app</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.camunda.bpm.dmn</groupId>
+            <artifactId>camunda-engine-dmn</artifactId>
+            <version>7.10.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>25.1-jre</version>
+        </dependency>
+        <dependency>
+            <groupId>javax.xml.bind</groupId>
+            <artifactId>jaxb-api</artifactId>
+            <version>2.3.0-b170201.1204</version>
+        </dependency>
+
+        <!-- https://mvnrepository.com/artifact/javax.activation/activation -->
+        <dependency>
+            <groupId>javax.activation</groupId>
+            <artifactId>activation</artifactId>
+            <version>1.1</version>
+        </dependency>
+
+        <!-- https://mvnrepository.com/artifact/org.glassfish.jaxb/jaxb-runtime -->
+        <dependency>
+            <groupId>org.glassfish.jaxb</groupId>
+            <artifactId>jaxb-runtime</artifactId>
+            <version>2.3.0-b170127.1453</version>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-api</artifactId>
+            <version>5.3.2</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.7.0</version>
+                <configuration>
+                    <source>8</source>
+                    <target>8</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>com.coveo</groupId>
+                <artifactId>fmt-maven-plugin</artifactId>
+                <version>2.6.0</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>format</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <mainClass>de.uniko.bks.statistic.PerformanceTester</mainClass>
+                        </manifest>
+                    </archive>
+                    <descriptorRefs>
+                        <descriptorRef>jar-with-dependencies</descriptorRef>
+                    </descriptorRefs>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>make-assembly</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/dmn-generator/src/main/java/de/uniko/bks/cli/CliArgument.java b/dmn-generator/src/main/java/de/uniko/bks/cli/CliArgument.java
new file mode 100644
index 0000000000000000000000000000000000000000..b8c231650d1bf5e3908fc368a1a309b5d233a462
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/cli/CliArgument.java
@@ -0,0 +1,137 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.cli;
+
+import de.uniko.bks.generator.entry.OutputEntryList;
+import de.uniko.bks.statistic.PerformanceTestConfiguration;
+import java.util.Arrays;
+
+/** Wrapper for all available cli arguments of the DMN gemerator */
+public class CliArgument {
+  private static final String FLAG_EXCEPTION_MESSAGE =
+      "Ignoring invalid or incomplete parameter and using the default value.";
+  /** Sign that all flags have */
+  private static String FLAG_SIGN = "-";
+  /** Flag which identifies the row number steps */
+  private static final String ROW_NUMBER_STEPS_FLAG = FLAG_SIGN + "r";
+
+  private static final String NUMBER_OF_TEST_RUNS_FLAG = FLAG_SIGN + "t";
+  private static final String NUMBER_OF_DATA_POINTS_FLAG = FLAG_SIGN + "d";
+  private static final String INITIAL_COLUMN_COUNT_FLAG = FLAG_SIGN + "icc";
+  private static final String INITIAL_ROW_COUNT_FLAG = FLAG_SIGN + "irc";
+  private static final String OUTPUT_ENTRY_LIST_FLAG = FLAG_SIGN + "o";
+  /** Difference in rows in each test dmn file */
+  private int rowSteps;
+  /** Number of runs for each file to calculate the average run-time */
+  private int numberOfTestRuns;
+  /** Amount (square root) of different data points (files) created */
+  private int numberOfDataPoints;
+  /** Number of columns the generator starts with */
+  private int initialColumnCount;
+  /** Number of rows the generator starts with */
+  private int initialRowCount;
+  /** List of output entries used in the dmn file (note the negations are created automatically) */
+  private OutputEntryList outputEntryList = new OutputEntryList();
+
+  public CliArgument(String[] args) {
+    this.rowSteps =
+        this.getFlagValue(
+            ROW_NUMBER_STEPS_FLAG, args, PerformanceTestConfiguration.getRowNumberSteps());
+    this.numberOfTestRuns =
+        this.getFlagValue(
+            NUMBER_OF_TEST_RUNS_FLAG, args, PerformanceTestConfiguration.getNumberOfTests());
+    this.numberOfDataPoints =
+        this.getFlagValue(
+            NUMBER_OF_DATA_POINTS_FLAG, args, PerformanceTestConfiguration.getNumberOfDataPoints());
+    this.initialColumnCount =
+        this.getFlagValue(
+                INITIAL_COLUMN_COUNT_FLAG,
+                args,
+                PerformanceTestConfiguration.getInitialColumnCount())
+            - 1;
+    this.initialRowCount =
+        this.getFlagValue(
+                INITIAL_ROW_COUNT_FLAG, args, PerformanceTestConfiguration.getInitialRowCount())
+            - 1;
+    this.outputEntryList.setValues(
+        this.getFlagValue(OUTPUT_ENTRY_LIST_FLAG, args, new OutputEntryList().getValues()));
+  }
+
+  /**
+   * Function which gets the value of a cli flag
+   *
+   * @param flag Flag of which the values is extracted
+   * @param args All cli arguments given
+   * @param defaultValue Default value if the argument is not set correctly
+   * @return The correct value of the cli argument
+   */
+  private int getFlagValue(String flag, String[] args, int defaultValue) {
+    try {
+      int flagIndex = Arrays.asList(args).indexOf(flag);
+      // Check if flag is set and the next item is not a flag
+      if (flagIndex >= 0 && !args[flagIndex + 1].contains(FLAG_SIGN)) {
+        return Integer.parseInt(args[flagIndex + 1]);
+      } else {
+        // Set the default value for the row steps
+        return defaultValue;
+      }
+    } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) {
+      System.err.println(FLAG_EXCEPTION_MESSAGE);
+    }
+    // Set the default value for the parameter
+    return defaultValue;
+  }
+
+  /**
+   * Function which gets the value of a cli flag
+   *
+   * @param flag Flag of which the values is extracted
+   * @param args All cli arguments given
+   * @param defaultValue Default value if the argument is not set correctly
+   * @return The correct value of the cli argument
+   */
+  private String[] getFlagValue(String flag, String[] args, String[] defaultValue) {
+    try {
+      int flagIndex = Arrays.asList(args).indexOf(flag);
+      // Check if flag is set and the next item is not a flag
+      if (flagIndex >= 0 && !args[flagIndex + 1].contains(FLAG_SIGN)) {
+        // Split the comma separated items of the flag
+        return args[flagIndex + 1].split(",");
+      } else {
+        // Set the default value for the row steps
+        return defaultValue;
+      }
+    } catch (ArrayIndexOutOfBoundsException e) {
+      System.err.println(FLAG_EXCEPTION_MESSAGE);
+    }
+    // Set the default value for the parameter
+    return defaultValue;
+  }
+
+  public int getRowSteps() {
+    return rowSteps;
+  }
+
+  public int getNumberOfTestRuns() {
+    return numberOfTestRuns;
+  }
+
+  public int getNumberOfDataPoints() {
+    return numberOfDataPoints;
+  }
+
+  public int getInitialColumnCount() {
+    return initialColumnCount;
+  }
+
+  public int getInitialRowCount() {
+    return initialRowCount;
+  }
+
+  public OutputEntryList getOutputEntryList() {
+    return outputEntryList;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/Date.java b/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/Date.java
new file mode 100644
index 0000000000000000000000000000000000000000..7d4d6b20c7068ae2a01503dd65156cf19474143b
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/Date.java
@@ -0,0 +1,111 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.dom.dfl;
+
+import de.uniko.bks.dom.dfl.rule.Comparator;
+import de.uniko.bks.dom.dfl.rule.RuleVariable;
+
+/** Class specifying how a date reasonable in SPINdle looks like */
+public class Date {
+  /** Year of a date (four digits: YYYY) */
+  private String year;
+  /** Month of a date (two digits: MM) */
+  private String month;
+  /** Day of a date (two digits: DD) */
+  private String day;
+  /** Hour of a date (two digits: hh) */
+  private String hour;
+  /** Minute of a date (two digits: ii) */
+  private String minute;
+  /** Second of the date (two digits: ss) */
+  private String second;
+  /** Comparator used for comparisons of dates */
+  private String comparator;
+
+  /** Constructor for an empty date */
+  public Date() {
+    this.year = "";
+    this.month = "";
+    this.day = "";
+    this.hour = "";
+    this.minute = "";
+    this.second = "";
+    this.comparator = Comparator.EQUALS.getValue();
+  }
+
+  /**
+   * Constructor for a date without a time
+   *
+   * @param year Year of a date (four digits: YYYY)
+   * @param month Month of a date (two digits: MM)
+   * @param day Day of a date (two digits: DD)
+   */
+  public Date(String year, String month, String day) {
+    this.year = year;
+    this.month = month;
+    this.day = day;
+    this.hour = "00";
+    this.minute = "00";
+    this.second = "00";
+    this.comparator = Comparator.EQUALS.getValue();
+  }
+
+  /**
+   * Constructor for a date with a time
+   *
+   * @param year Year of a date (four digits: YYYY)
+   * @param month Month of a date (two digits: MM)
+   * @param day Day of a date (two digits: DD)
+   * @param hour Hour of a date (two digits: hh)
+   * @param minute Minute of a date (two digits: ii)
+   * @param second Second of the date (two digits: ss)
+   */
+  public Date(String year, String month, String day, String hour, String minute, String second) {
+    this.year = year;
+    this.month = month;
+    this.day = day;
+    this.hour = hour;
+    this.minute = minute;
+    this.second = second;
+    this.comparator = Comparator.EQUALS.getValue();
+  }
+
+  /**
+   * Getter for the date comparator
+   *
+   * @return The comparator used for date comparisons
+   */
+  public String getComparator() {
+    return comparator;
+  }
+
+  /**
+   * Setter for the date comparator
+   *
+   * @param comparator The comparator used for date comparisons
+   */
+  public void setComparator(String comparator) {
+    this.comparator = comparator;
+  }
+
+  @Override
+  public String toString() {
+    return RuleVariable.VAR_SIGN.getValue()
+        + "date("
+        + year
+        + ','
+        + month
+        + ','
+        + day
+        + ','
+        + hour
+        + ','
+        + minute
+        + ','
+        + second
+        + ')';
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/Fact.java b/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/Fact.java
new file mode 100644
index 0000000000000000000000000000000000000000..b8d8b3404d5981e3b7af27cfbe747b3aaf487411
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/Fact.java
@@ -0,0 +1,90 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.dom.dfl;
+
+/**
+ * Class representing a fact of any type
+ *
+ * @param <T> Java type of the fact
+ */
+public class Fact<T> {
+  /** Name of the fact */
+  private String name;
+  /** Value of the fact */
+  private T value;
+  /** Java class the value of the fact belongs to */
+  private Class<T> type;
+
+  /** Constructor for an empty fact */
+  public Fact() {}
+
+  /**
+   * Constructor for a completely set fact
+   *
+   * @param name Name of the fact
+   * @param value Value of the fact
+   * @param type Java class the value of the fact belongs to
+   */
+  public Fact(String name, T value, Class<T> type) {
+    this.name = name;
+    this.value = value;
+    this.type = type;
+  }
+
+  /**
+   * Getter for the fact name
+   *
+   * @return The name of the fact
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Setter for the fact name
+   *
+   * @param name The name of the fact
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * Getter for the value of the fact
+   *
+   * @return The value of the fact
+   */
+  public T getValue() {
+    return value;
+  }
+
+  /**
+   * Getter for the value of the fact
+   *
+   * @param value The value of the fact
+   */
+  public void setValue(T value) {
+    this.value = value;
+  }
+
+  /**
+   * Getter for the type of the fact
+   *
+   * @return The class name of the type of the fact
+   */
+  public Class<T> getType() {
+    return type;
+  }
+
+  /**
+   * Setter for the type of the fact
+   *
+   * @param type The class name of the type of the fact
+   */
+  public void setType(Class<T> type) {
+    this.type = type;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/LiteralRange.java b/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/LiteralRange.java
new file mode 100644
index 0000000000000000000000000000000000000000..fed5ce4a1bcc96d1e6d2efe3800b31bac77d92e8
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/LiteralRange.java
@@ -0,0 +1,114 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.dom.dfl;
+
+/**
+ * Class which represents a wrapper for literals containing a range
+ *
+ * @param <T> Type of the limits of the range
+ */
+public class LiteralRange<T> {
+  /** Whether or not the literal contains a range */
+  private boolean range;
+  /** Comparator for the lower limit of the range */
+  private String lowerLimitComparator;
+  /** Comparator for the upper limit of the range */
+  private String upperLimitComparator;
+  /** Lower limit of the range */
+  private T lowerLimit;
+  /** Upper limit of the range */
+  private T upperLimit;
+
+  /**
+   * Construtor for an empty range
+   *
+   * @param range Whether or not the literal contains a range
+   */
+  public LiteralRange(boolean range) {
+    this.range = range;
+  }
+
+  /**
+   * Getter for the range
+   *
+   * @return Whether or not the literal contains a range
+   */
+  public boolean isRange() {
+    return range;
+  }
+
+  /**
+   * Getter for the lower limit comparator
+   *
+   * @return The lower limit comparator
+   */
+  public String getLowerLimitComparator() {
+    return lowerLimitComparator;
+  }
+
+  /**
+   * Setter for the lower limit comparator
+   *
+   * @param lowerLimitComparator The lower limit comparator
+   */
+  public void setLowerLimitComparator(String lowerLimitComparator) {
+    this.lowerLimitComparator = lowerLimitComparator;
+  }
+
+  /**
+   * Getter for the upper limit comparator
+   *
+   * @return The upper limit comparator
+   */
+  public String getUpperLimitComparator() {
+    return upperLimitComparator;
+  }
+
+  /**
+   * Setter for the upper limit comparator
+   *
+   * @param upperLimitComparator The upper limit comparator
+   */
+  public void setUpperLimitComparator(String upperLimitComparator) {
+    this.upperLimitComparator = upperLimitComparator;
+  }
+
+  /**
+   * Getter for the lower limit
+   *
+   * @return The lower limit
+   */
+  public T getLowerLimit() {
+    return lowerLimit;
+  }
+
+  /**
+   * Setter for the lower limit
+   *
+   * @param lowerLimit The lower limit
+   */
+  public void setLowerLimit(T lowerLimit) {
+    this.lowerLimit = lowerLimit;
+  }
+
+  /**
+   * Getter for the upper limit
+   *
+   * @return The upper limit
+   */
+  public T getUpperLimit() {
+    return upperLimit;
+  }
+
+  /**
+   * Setter for the upper limit
+   *
+   * @param upperLimit The upper limit
+   */
+  public void setUpperLimit(T upperLimit) {
+    this.upperLimit = upperLimit;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/rule/Comparator.java b/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/rule/Comparator.java
new file mode 100644
index 0000000000000000000000000000000000000000..f3a782a1d7c3fd4f9509a0e1bdf734e346a3d4d1
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/rule/Comparator.java
@@ -0,0 +1,63 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.dom.dfl.rule;
+
+/** Enum containing all mathematical comparators for comparison expressions */
+public enum Comparator {
+  /** Comparator for smaller comparisons */
+  SMALLER("<"),
+  /** Comparator for smaller or equals comparisons */
+  SMALLER_OR_EQUALS("<="),
+  /** Comparator for equals comparisons */
+  EQUALS("=="),
+  /** Comparator for greater or equals comparisons */
+  GREATER_OR_EQUALS(">="),
+  /** Comparator for greater comparisons */
+  GREATER(">");
+  /** Actual value of the enum */
+  private String value;
+
+  /**
+   * Constructor to set the value of each enum entry
+   *
+   * @param value String value of the enum
+   */
+  Comparator(String value) {
+    this.value = value;
+  }
+
+  /**
+   * Getter for the (string) value of one enum entry
+   *
+   * @return The value of the enum entry
+   */
+  public String getValue() {
+    return value;
+  }
+
+  /**
+   * Function which gets the opposite of a given comparator
+   *
+   * @param comparator Comparator or string containing the comparator
+   * @return The comparator which describes the opposite set
+   */
+  public static String getOppositeValue(String comparator) {
+    if (comparator.contains(SMALLER_OR_EQUALS.value)) {
+      return GREATER.value;
+    }
+    if (comparator.contains(GREATER_OR_EQUALS.value)) {
+      return SMALLER.value;
+    }
+    if (comparator.contains(SMALLER.value)) {
+      return GREATER_OR_EQUALS.value;
+    }
+    if (comparator.contains(GREATER.value)) {
+      return SMALLER_OR_EQUALS.value;
+    }
+
+    return EQUALS.value;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/rule/RuleArrow.java b/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/rule/RuleArrow.java
new file mode 100644
index 0000000000000000000000000000000000000000..2725b3b41aaf0e91d6943f52a611e348f73c81f8
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/rule/RuleArrow.java
@@ -0,0 +1,38 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.dom.dfl.rule;
+
+/** Enum containing all supported arrows used in a DFL rule */
+public enum RuleArrow {
+  /** Arrow for strict rules */
+  STRICT_RULE("->"),
+  /** Arrow for defeasible rules */
+  DEFEASIBLE_RULE("=>"),
+  /** Arrow for facts */
+  FACT(">>"),
+  /** Arrow for superiorities */
+  SUPERIORITY(">");
+  /** Actual value of the enum */
+  private String value;
+
+  /**
+   * Constructor to set the value of each enum entry
+   *
+   * @param value String value of the enum
+   */
+  RuleArrow(String value) {
+    this.value = value;
+  }
+
+  /**
+   * Getter for the (string) value of one enum entry
+   *
+   * @return The value of the enum entry
+   */
+  public String getValue() {
+    return value;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/rule/RuleDelimiter.java b/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/rule/RuleDelimiter.java
new file mode 100644
index 0000000000000000000000000000000000000000..6c39ef4d614ad2dde7c3b45d0d1f1be1456c43ae
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/rule/RuleDelimiter.java
@@ -0,0 +1,34 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.dom.dfl.rule;
+
+/** Enum containing all delimiters used in a DFL rule */
+public enum RuleDelimiter {
+  /** Delimiter between rule id and rule literals */
+  ID(":"),
+  /** Delimiter replacing whitespaces in dfl rules */
+  WHITESPACE("_");
+  /** Actual value of the enum */
+  private String value;
+
+  /**
+   * Constructor to set the value of each enum entry
+   *
+   * @param value String value of the enum
+   */
+  RuleDelimiter(String value) {
+    this.value = value;
+  }
+
+  /**
+   * Getter for the (string) value of one enum entry
+   *
+   * @return The value of the enum entry
+   */
+  public String getValue() {
+    return value;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/rule/RuleId.java b/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/rule/RuleId.java
new file mode 100644
index 0000000000000000000000000000000000000000..bfc4398926c196e8c2d9cfeb7b063df7d64fee8e
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/rule/RuleId.java
@@ -0,0 +1,127 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.dom.dfl.rule;
+
+import de.uniko.bks.util.StringSanitizer;
+import java.util.Comparator;
+
+/** Class representing a DFL rule identifier */
+public class RuleId {
+  /** Delimiter between two parts of the ruleId */
+  private static final String PART_DELIMITER =
+      RuleDelimiter.WHITESPACE.getValue()
+          + RuleDelimiter.WHITESPACE.getValue()
+          + RuleDelimiter.WHITESPACE.getValue();
+
+  /** XML id of the rule in the DMN */
+  private String xmlId;
+  /** Id of the decision in the DMN */
+  private String decisionId;
+  /** Number of the rule */
+  private int number;
+  /** Subnumber of the rule (only important on split up rules) */
+  private int subNumber;
+  /** Priority of the rule */
+  private int priority;
+
+  /**
+   * Constructor to completely initialize a RuleId
+   *
+   * @param xmlId XML id of the rule in the DMN
+   * @param decisionId Id of the decision in the DMN
+   * @param number Number of the rule
+   * @param subNumber Subnumber of the rule (only important on split up rules)
+   * @param priority Priority of the rule
+   */
+  public RuleId(String xmlId, String decisionId, int number, int subNumber, int priority) {
+    // Replace illegal characters
+    this.xmlId = StringSanitizer.sanitize(xmlId, true, false, false, true);
+    this.decisionId = decisionId;
+    this.number = number;
+    this.subNumber = subNumber;
+    this.priority = priority;
+  }
+
+  /**
+   * Getter for the XML id of the rule in the DMN
+   *
+   * @return The XML id of the rule in the DMN
+   */
+  public String getXmlId() {
+    return xmlId;
+  }
+
+  /**
+   * Getter for the id of the decision in the DMN
+   *
+   * @return The id of the decision in the DMN
+   */
+  public String getDecisionId() {
+    return decisionId;
+  }
+
+  /**
+   * Getter for the number of the rule
+   *
+   * @return The number of the rule
+   */
+  public int getNumber() {
+    return number;
+  }
+
+  /**
+   * Getter for the subnumber of the rule (only important on split up rules)
+   *
+   * @return The subnumber of the rule
+   */
+  public int getSubNumber() {
+    return subNumber;
+  }
+
+  /**
+   * Getter for the priority of the rule
+   *
+   * @return The priority of the rule
+   */
+  public int getPriority() {
+    return priority;
+  }
+
+  /**
+   * Getter for the delimiter between two parts of the ruleId
+   *
+   * @return The delimiter between two parts of the ruleId
+   */
+  public static String getPartDelimiter() {
+    return PART_DELIMITER;
+  }
+
+  /** Define the comparator to sort the ruleIds by their number */
+  public static Comparator<RuleId> COMPARE_BY_NUMBER = Comparator.comparingInt(one -> one.number);
+
+  /** Define the comparator to sort th ruleIds by their priority */
+  public static Comparator<RuleId> COMPARE_BY_PRIORITY =
+      Comparator.comparingInt(one -> one.priority);
+
+  @Override
+  public String toString() {
+    // Do not render the xml id on facts
+    if (xmlId.equals("")) {
+      return this.decisionId + PART_DELIMITER + this.number + RuleDelimiter.ID.getValue();
+    }
+
+    return this.xmlId
+        + PART_DELIMITER
+        + this.decisionId
+        + PART_DELIMITER
+        + this.number
+        + PART_DELIMITER
+        + this.subNumber
+        + PART_DELIMITER
+        + this.priority
+        + RuleDelimiter.ID.getValue();
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/rule/RuleType.java b/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/rule/RuleType.java
new file mode 100644
index 0000000000000000000000000000000000000000..63625718131bfcd65851f54ad528724d02ca2d48
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/rule/RuleType.java
@@ -0,0 +1,42 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.dom.dfl.rule;
+
+/** Enum containing available rule types */
+public enum RuleType {
+  /** Rule type for booleans */
+  BOOLEAN("boolean"),
+  /** Rule type for double */
+  DOUBLE("double"),
+  /** Rule type for dates */
+  DATE("date"),
+  /** Rule type for integers */
+  INT("integer"),
+  /** Rule type for longs */
+  LONG("long"),
+  /** Rule type for integers */
+  STRING("string");
+  /** Actual value of the enum */
+  private String value;
+
+  /**
+   * Constructor to set the value of each enum entry
+   *
+   * @param value String value of the enum
+   */
+  RuleType(String value) {
+    this.value = value;
+  }
+
+  /**
+   * Getter for the (string) value of one enum entry
+   *
+   * @return The value of the enum entry
+   */
+  public String getValue() {
+    return value;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/rule/RuleVariable.java b/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/rule/RuleVariable.java
new file mode 100644
index 0000000000000000000000000000000000000000..716dfe6cc2ca112e6d99bc972f42ce1349cd8523
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/dom/dfl/rule/RuleVariable.java
@@ -0,0 +1,36 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.dom.dfl.rule;
+
+/** Enum containing all delimiters used in variables of a DLF rule */
+public enum RuleVariable {
+  /** Sign for DFL variables */
+  VAR_SIGN("@"),
+  /** Set expression for DFL variables */
+  SET("set "),
+  /** Allocation of DFL expressions */
+  ALLOCATION("=");
+  /** Actual value of the enum */
+  private String value;
+
+  /**
+   * Constructor to set the value of each enum entry
+   *
+   * @param value String value of the enum
+   */
+  RuleVariable(String value) {
+    this.value = value;
+  }
+
+  /**
+   * Getter for the (string) value of one enum entry
+   *
+   * @return The value of the enum entry
+   */
+  public String getValue() {
+    return value;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/Decision.java b/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/Decision.java
new file mode 100644
index 0000000000000000000000000000000000000000..98916f0bac8ea30d32567f5f99cb53f73bdc330f
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/Decision.java
@@ -0,0 +1,81 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.dom.dmn;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/** Class specifying a dmn decision */
+@XmlRootElement(name = "decision")
+public class Decision {
+  /** XML id of the Decision */
+  private String id;
+  /** XML name of the Decision */
+  private String name;
+  /** DecisionTable contained in the Decision */
+  private DecisionTable dmnTable;
+
+  /** Constructor of an empty Decision */
+  public Decision() {}
+
+  /**
+   * Getter for the XML id of the Decision
+   *
+   * @return The XML id of the Decision
+   */
+  @XmlAttribute(name = "id")
+  public String getId() {
+    return id;
+  }
+
+  /**
+   * Setter for the XML id of the Decision
+   *
+   * @param id XML id of the Decision
+   */
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  /**
+   * Getter for the XML name of the Decision
+   *
+   * @return The XML name of the Decision
+   */
+  @XmlAttribute(name = "name")
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Setter for the XML name of the Decision
+   *
+   * @param name The XML name of the Decision
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * Getter for the DecisionTable contained int the Decision
+   *
+   * @return The DecisionTable contained in the Decision
+   */
+  @XmlElement(name = "decisionTable")
+  public DecisionTable getDmnTable() {
+    return dmnTable;
+  }
+
+  /**
+   * Setter for the DecisionTable contained int the Decision
+   *
+   * @param dmnTable The DecisionTable contained in the Decision
+   */
+  public void setDmnTable(DecisionTable dmnTable) {
+    this.dmnTable = dmnTable;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/DecisionTable.java b/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/DecisionTable.java
new file mode 100644
index 0000000000000000000000000000000000000000..6e382603cab7aa60db334b04442a3bd679cb1a6a
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/DecisionTable.java
@@ -0,0 +1,124 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.dom.dmn;
+
+import de.uniko.bks.dom.dmn.header.OutputHeader;
+import java.util.ArrayList;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+/** Class specifying a dmn DecisionTable */
+@XmlType(propOrder = {"input", "outputHeader", "dmnRule"})
+public class DecisionTable {
+  /** XML id of the decision table */
+  private String id;
+  /** HitPolicy of the table */
+  private String hitPolicy;
+  /** XML input elements of the table */
+  private ArrayList<Input> input;
+  /** OutputHeader (meta-information about the output) of the table */
+  private OutputHeader outputHeader;
+  /** Rules contained in the table */
+  private ArrayList<DmnRule> dmnRule;
+
+  /** Constructor to initialize an empty DecisionTable */
+  public DecisionTable() {}
+
+  /**
+   * Getter for the XML id of the decision table
+   *
+   * @return The XML id of the decision table
+   */
+  @XmlAttribute
+  public String getId() {
+    return id;
+  }
+
+  /**
+   * Setter for the XML id of the decision table
+   *
+   * @param id The XML id of the decision table
+   */
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  /**
+   * Getter for the HitPolicy of a table
+   *
+   * @return The HitPolicy of the table
+   */
+  @XmlAttribute
+  public String getHitPolicy() {
+    return hitPolicy;
+  }
+
+  /**
+   * Setter for the HitPolicy of a table
+   *
+   * @param hitPolicy The HitPolicy of the table
+   */
+  public void setHitPolicy(String hitPolicy) {
+    this.hitPolicy = hitPolicy;
+  }
+
+  /**
+   * Getter for the XML input elements of the table
+   *
+   * @return The XML input elements of the table
+   */
+  @XmlElement(name = "input")
+  public ArrayList<Input> getInput() {
+    return input;
+  }
+
+  /**
+   * Getter for the OutputHeader (meta-information about the output) of the table
+   *
+   * @return The OutputHeader (meta-information about the output) of the table
+   */
+  @XmlElement(name = "output")
+  public OutputHeader getOutputHeader() {
+    return outputHeader;
+  }
+  /**
+   * Setter for the XML input elements of the table
+   *
+   * @param input The XML input elements of the table
+   */
+  public void setInput(ArrayList<Input> input) {
+    this.input = input;
+  }
+
+  /**
+   * Getter for the rules contained in the table
+   *
+   * @return The rules contained in the table
+   */
+  @XmlElement(name = "rule")
+  public ArrayList<DmnRule> getDmnRule() {
+    return dmnRule;
+  }
+
+  /**
+   * Setter for the rules contained in the table
+   *
+   * @param dmnRule The rules contained in the table
+   */
+  public void setDmnRule(ArrayList<DmnRule> dmnRule) {
+    this.dmnRule = dmnRule;
+  }
+
+  /**
+   * Setter for the OutputHeader (meta-information about the output) of the table
+   *
+   * @param outputHeader The OutputHeader (meta-information about the output) of the table
+   */
+  public void setOutputHeader(OutputHeader outputHeader) {
+    this.outputHeader = outputHeader;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/DmnRule.java b/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/DmnRule.java
new file mode 100644
index 0000000000000000000000000000000000000000..478ee5e98b36757456daf39826170cc63edff753
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/DmnRule.java
@@ -0,0 +1,79 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.dom.dmn;
+
+import de.uniko.bks.dom.dmn.entry.InputEntry;
+import de.uniko.bks.dom.dmn.entry.OutputEntry;
+import java.util.ArrayList;
+import javax.xml.bind.annotation.XmlAttribute;
+
+/** Class specifying a single DMNRule */
+public class DmnRule {
+  /** XML id of the rule */
+  private String id;
+  /** List of inputEntries of the rule */
+  private ArrayList<InputEntry> inputEntry;
+  /** OutputEntry of the rule */
+  private OutputEntry outputEntry;
+
+  /** Constructor to initialize an empty DmnRule */
+  public DmnRule() {}
+
+  /**
+   * Getter for the XML id of the rule
+   *
+   * @return The XML id of the rule
+   */
+  @XmlAttribute
+  public String getId() {
+    return id;
+  }
+
+  /**
+   * Setter for the XML id of the rule
+   *
+   * @param id The XML id of the rule
+   */
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  /**
+   * Getter for the List of inputEntries of the rule
+   *
+   * @return The List of inputEntries of the rule
+   */
+  public ArrayList<InputEntry> getInputEntry() {
+    return inputEntry;
+  }
+
+  /**
+   * Setter for the List of inputEntries of the rule
+   *
+   * @param inputEntry The List of inputEntries of the rule
+   */
+  public void setInputEntry(ArrayList<InputEntry> inputEntry) {
+    this.inputEntry = inputEntry;
+  }
+
+  /**
+   * Getter for OutputEntry of the rule
+   *
+   * @return The OutputEntry of the rule
+   */
+  public OutputEntry getOutputEntry() {
+    return outputEntry;
+  }
+
+  /**
+   * Setter for OutputEntry of the rule
+   *
+   * @param outputEntry The OutputEntry of the rule
+   */
+  public void setOutputEntry(OutputEntry outputEntry) {
+    this.outputEntry = outputEntry;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/HitPolicy.java b/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/HitPolicy.java
new file mode 100644
index 0000000000000000000000000000000000000000..090fd2034b6f3658c7c70f64a6eed6479862ea61
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/HitPolicy.java
@@ -0,0 +1,53 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.dom.dmn;
+
+/** Enum containing all supported hit policies for DMN decision tables */
+public enum HitPolicy {
+  /** Entry for the ANY hit policy */
+  ANY("ANY"),
+  /** Entry for the COLLECT hit policy */
+  COLLECT("COLLECT"),
+  /** Entry for the FIRST hit policy */
+  FIRST("FIRST"),
+  /** Entry for the OUTPUT ORDER hit policy */
+  OUTPUT_ORDER("OUTPUT ORDER"),
+  /** Entry for the PRIORITY hit policy */
+  PRIORITY("PRIORITY"),
+  /** Entry for the RULE ORDER hit policy */
+  RULE_ORDER("RULE ORDER"),
+  /** Entry for the UNIQUE hit policy */
+  UNIQUE("UNIQUE");
+  /** Actual value of the enum */
+  private String value;
+
+  /**
+   * Constructor to set the value of each enum entry
+   *
+   * @param value String value of the enum
+   */
+  HitPolicy(String value) {
+    this.value = value;
+  }
+
+  /**
+   * Getter for the (string) value of one enum entry
+   *
+   * @return The value of the enum entry
+   */
+  public String getValue() {
+    return value;
+  }
+
+  /**
+   * Getter for the (string) value of the default enum entry
+   *
+   * @return The value of the default enum entry
+   */
+  public static String getDefault() {
+    return UNIQUE.value;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/Input.java b/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/Input.java
new file mode 100644
index 0000000000000000000000000000000000000000..6b93ab801d2857a5616546f926d4ca972d90a527
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/Input.java
@@ -0,0 +1,83 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.dom.dmn;
+
+import de.uniko.bks.dom.dmn.header.InputHeader;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+
+/** Class specifying a DMN Input */
+public class Input {
+  /** XML id of the Input */
+  private String id;
+  /** XML label of the Input */
+  private String label;
+  /** InputHeader of the Input element */
+  private InputHeader inputHeader;
+
+  /** Constructor to initialize an empty Input */
+  public Input() {}
+
+  /**
+   * Constructor to initialize a completely set Input
+   *
+   * @param id The XML id of the Input
+   * @param label The XML label of the Input
+   * @param inputHeader The InputHeader of the Input element
+   */
+  public Input(String id, String label, InputHeader inputHeader) {
+    this.id = id;
+    this.label = label;
+    this.inputHeader = inputHeader;
+  }
+
+  @XmlAttribute
+  public String getId() {
+    return id;
+  }
+
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  /**
+   * Getter for the XML label of the Input
+   *
+   * @return The XML label of the Input
+   */
+  @XmlAttribute
+  public String getLabel() {
+    return label;
+  }
+
+  /**
+   * Setter for the XML label of the Input
+   *
+   * @param label The XML label of the Input
+   */
+  public void setLabel(String label) {
+    this.label = label;
+  }
+
+  /**
+   * Getter for the InputHeader of the Input element
+   *
+   * @return The InputHeader of the Input element
+   */
+  @XmlElement(name = "inputExpression")
+  public InputHeader getInputHeader() {
+    return inputHeader;
+  }
+
+  /**
+   * Setter for the InputHeader of the Input element
+   *
+   * @param inputHeader The InputHeader of the Input element
+   */
+  public void setInputHeader(InputHeader inputHeader) {
+    this.inputHeader = inputHeader;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/entry/InputEntry.java b/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/entry/InputEntry.java
new file mode 100644
index 0000000000000000000000000000000000000000..93083551fa5095afb1b6789392e7e529ea868b53
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/entry/InputEntry.java
@@ -0,0 +1,69 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.dom.dmn.entry;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+
+/** Class specifying a dmn InputEntry */
+public class InputEntry {
+  /** XML id of the InputEntry */
+  private String id;
+  /** Text/value of the InputEntry */
+  private String text;
+
+  /** Constructor for an empty InputEntry */
+  public InputEntry() {}
+
+  /**
+   * Constructor for a completely initialized InputEntry
+   *
+   * @param id XML id of the InputEntry
+   * @param text Text/value of the InputEntry
+   */
+  public InputEntry(String id, String text) {
+    this.id = id;
+    this.text = text;
+  }
+
+  /**
+   * Getter for the InputEntry id
+   *
+   * @return The id of the InputEntry
+   */
+  @XmlAttribute
+  public String getId() {
+    return id;
+  }
+
+  /**
+   * Setter for the InputEntry id
+   *
+   * @param id The id of the InputEntry
+   */
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  /**
+   * Getter for the InputEntry text/value
+   *
+   * @return The text/value of the InputEntry
+   */
+  @XmlElement
+  public String getText() {
+    return text;
+  }
+
+  /**
+   * Setter for the InputEntry text/value
+   *
+   * @param text The text/value of the InputEntry
+   */
+  public void setText(String text) {
+    this.text = text;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/entry/OutputEntry.java b/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/entry/OutputEntry.java
new file mode 100644
index 0000000000000000000000000000000000000000..c849d0c533d4c81e04bdbdb5e4a5792c5220360d
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/entry/OutputEntry.java
@@ -0,0 +1,65 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.dom.dmn.entry;
+
+import javax.xml.bind.annotation.XmlAttribute;
+
+/** Class specifying a dmn OutputEntry */
+public class OutputEntry {
+  /** XML id of the OutputEntry */
+  private String id;
+  /** Text/value of the OutputEntry */
+  private String text;
+
+  /** Constructor for an empty OutputEntry */
+  public OutputEntry() {}
+
+  /**
+   * Constructor for an OutputEntry with an initial text/value
+   *
+   * @param text Text/value of the OutputEntry
+   */
+  public OutputEntry(String text) {
+    this.text = text;
+  }
+
+  /**
+   * Getter for the OutputEntry id
+   *
+   * @return The id of the OutputEntry
+   */
+  @XmlAttribute
+  public String getId() {
+    return id;
+  }
+
+  /**
+   * Setter for the OutputEntry id
+   *
+   * @param id The id of the OutputEntry
+   */
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  /**
+   * Getter for the OutputEntry text/value
+   *
+   * @return The text/value of the OutputEntry
+   */
+  public String getText() {
+    return text;
+  }
+
+  /**
+   * Setter for the OutputEntry text/value
+   *
+   * @param text The text/value of the OutputEntry
+   */
+  public void setText(String text) {
+    this.text = text;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/entry/RuleEntry.java b/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/entry/RuleEntry.java
new file mode 100644
index 0000000000000000000000000000000000000000..a12357666f7e2c9624436b7953b99bd923673663
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/entry/RuleEntry.java
@@ -0,0 +1,138 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.dom.dmn.entry;
+
+/**
+ * Class specifying a common transfer object encapsulating a rule entry
+ *
+ * @param <T> Type (java class) of the RuleEntry value
+ */
+public class RuleEntry<T> {
+  /** Type (java class) of the value */
+  private String type;
+  /** Value of the RuleEntry */
+  private T value;
+  /** Name (i.e. DMN table header) of the RuleEntry */
+  private String name;
+  /** Whether the values is negated in a logical sense or not */
+  private boolean negated;
+  /**
+   * Whether the RuleEntry is an output entry (this property is needed to avoid issues with
+   * SPINdle's way of handling head literals)
+   */
+  private boolean output;
+
+  /**
+   * Constructor for a simple non-negated RuleEntry
+   *
+   * @param type Type (java class) of the value
+   * @param value Value of the RuleEntry
+   * @param headerName Name (i.e. DMN table header) of the RuleEntry
+   */
+  public RuleEntry(String type, T value, String headerName) {
+    this.type = type;
+    this.value = value;
+    this.name = headerName;
+    this.negated = false;
+    this.output = false;
+  }
+
+  /**
+   * Constructor for a possible negated RuleEntry
+   *
+   * @param type Type (java class) of the value
+   * @param value Value of the RuleEntry
+   * @param headerName Name (i.e. DMN table header) of the RuleEntry
+   * @param negated Whether the values is negated in a logical sense or not
+   */
+  public RuleEntry(String type, T value, String headerName, boolean negated) {
+    this.type = type;
+    this.value = value;
+    this.name = headerName;
+    this.negated = negated;
+    this.output = false;
+  }
+
+  /**
+   * Constructor for an RuleEntry which is an dmn output
+   *
+   * @param type Type (java class) of the value
+   * @param value Value of the RuleEntry
+   * @param headerName Name (i.e. DMN table header) of the RuleEntry
+   * @param negated Whether the values is negated in a logical sense or not
+   * @param output Whether the RuleEntry is an output entry
+   */
+  public RuleEntry(String type, T value, String headerName, boolean negated, boolean output) {
+    this.type = type;
+    this.value = value;
+    this.name = headerName;
+    this.negated = negated;
+    this.output = output;
+  }
+
+  /**
+   * Getter for the RuleEntry type
+   *
+   * @return The type of the RuleEntry
+   */
+  public String getType() {
+    return type;
+  }
+
+  /**
+   * Getter for the RuleEntry value
+   *
+   * @return The value of the RuleEntry
+   */
+  public T getValue() {
+    return value;
+  }
+
+  /**
+   * Setter for the RuleEntry value
+   *
+   * @param value The value of the RuleEntry
+   */
+  public void setValue(T value) {
+    this.value = value;
+  }
+
+  /**
+   * Getter for the RuleEntry name
+   *
+   * @return The name of the RuleEntry
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Getter for the RuleEntry negated property
+   *
+   * @return Whether or not the RuleEntry is negated
+   */
+  public boolean isNegated() {
+    return negated;
+  }
+
+  /**
+   * Getter for the RuleEntry output property
+   *
+   * @return Whether or not the RuleEntry is an output
+   */
+  public boolean isOutput() {
+    return output;
+  }
+
+  /**
+   * Setter for the RuleEntry output property
+   *
+   * @param output Whether or not the RuleEntry is an output
+   */
+  public void setOutput(boolean output) {
+    this.output = output;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/header/Header.java b/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/header/Header.java
new file mode 100644
index 0000000000000000000000000000000000000000..ff46ea74257cb8e6cd4921b567054eb0040377cd
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/header/Header.java
@@ -0,0 +1,56 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.dom.dmn.header;
+
+import javax.xml.bind.annotation.XmlAttribute;
+
+/** Interface specifying which functions a header has to have */
+public abstract class Header {
+  /** The XML id of the Header */
+  String id;
+  /** The type of the Header */
+  String type;
+  /** The text/value of the Header */
+  String text;
+
+  /**
+   * Getter for the XML id of the Header
+   *
+   * @return The XML id of the Header
+   */
+  @XmlAttribute
+  public String getId() {
+    return id;
+  }
+
+  /**
+   * Setter for the XML id of the Header
+   *
+   * @param id The XML id of the Header
+   */
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  /**
+   * Getter for the Header type
+   *
+   * @return The type of the Header
+   */
+  @XmlAttribute(name = "typeRef")
+  public String getType() {
+    return type;
+  }
+
+  /**
+   * Setter for the Header type
+   *
+   * @param type The type of the Header
+   */
+  public void setType(String type) {
+    this.type = type;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/header/InputHeader.java b/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/header/InputHeader.java
new file mode 100644
index 0000000000000000000000000000000000000000..13e989a043890afc56c156b77926a9b48f32d2f2
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/header/InputHeader.java
@@ -0,0 +1,46 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.dom.dmn.header;
+
+import javax.xml.bind.annotation.XmlElement;
+
+/** Class specifying a dmn InputHeader */
+public class InputHeader extends Header {
+  /** Constructor of an empty InputHeader */
+  public InputHeader() {}
+
+  /**
+   * Constructor for a completely initialized InputHeader
+   *
+   * @param id The XML id of the Header
+   * @param type The type of the Header
+   * @param text The text/value of the Header
+   */
+  public InputHeader(String id, String type, String text) {
+    this.id = id;
+    this.type = type;
+    this.text = text;
+  }
+
+  /**
+   * Getter for the Header text/value
+   *
+   * @return The text/value of the Header
+   */
+  @XmlElement
+  public String getText() {
+    return text;
+  }
+
+  /**
+   * Setter for the Header text/value
+   *
+   * @param text The text/value of the Header
+   */
+  public void setText(String text) {
+    this.text = text;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/header/OutputHeader.java b/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/header/OutputHeader.java
new file mode 100644
index 0000000000000000000000000000000000000000..a146522427ebce4c75afbfd87e57dd59cdc52a07
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/header/OutputHeader.java
@@ -0,0 +1,56 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.dom.dmn.header;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+
+/** Class specifying a dmn OutputHeader */
+public class OutputHeader extends Header {
+  /** The outputValues (priority of the output elements/output order) */
+  private OutputValues outputValues;
+
+  /** Constructor of an empty OutputHeader */
+  public OutputHeader() {}
+
+  /**
+   * Getter for the Header name attribute
+   *
+   * @return The name attribute of the Header
+   */
+  @XmlAttribute(name = "name")
+  public String getText() {
+    return text;
+  }
+
+  /**
+   * Setter for the Header name attribute
+   *
+   * @param text The name attribute of the Header
+   */
+  public void setText(String text) {
+    this.text = text;
+  }
+
+  /**
+   * Getter for the outputValues (priority of the output elements/output order)
+   *
+   * @return The outputValues of the dmn table header
+   */
+  @XmlElement(name = "outputValues")
+  public OutputValues getOutputValues() {
+    return outputValues;
+  }
+
+  /**
+   * Setter for the outputValues (priority of the output elements/output order)
+   *
+   * @param outputValues The outputValues of the dmn table header
+   */
+  public void setOutputValues(OutputValues outputValues) {
+    this.outputValues = outputValues;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/header/OutputValues.java b/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/header/OutputValues.java
new file mode 100644
index 0000000000000000000000000000000000000000..060084045b1cb44ced16a07601acb87719bd69d5
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/dom/dmn/header/OutputValues.java
@@ -0,0 +1,70 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.dom.dmn.header;
+
+import de.uniko.bks.util.StringSanitizer;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+
+/** Class specifying the OutputValues of a dmn table header */
+public class OutputValues {
+  /** The XML id of the OutputValues */
+  private String id;
+  /** The text/value of the OutputValues as comma separated list */
+  private String text;
+
+  /** Constructor for empty OutputValues */
+  public OutputValues() {}
+
+  /**
+   * Constructor for completely initialized OutputValues
+   *
+   * @param id The XML id of the OutputValues
+   * @param text The text/value of the OutputValues as comma separated list
+   */
+  public OutputValues(String id, String text) {
+    this.id = id;
+    this.text = text;
+  }
+
+  /**
+   * Getter for the XML id of the OutputValues
+   *
+   * @return The XML id of the OutputValues
+   */
+  @XmlAttribute
+  public String getId() {
+    return id;
+  }
+
+  /**
+   * Setter for the XML id of the OutputValues
+   *
+   * @param id The XML id of the OutputValues
+   */
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  /**
+   * Getter for the text/value of the OutputValues
+   *
+   * @return The text/value of the OutputValues
+   */
+  @XmlElement
+  public String getText() {
+    return text;
+  }
+
+  /**
+   * Setter for the text/value of the OutputValues
+   *
+   * @param text The text/value of the OutputValues
+   */
+  public void setText(String text) {
+    this.text = StringSanitizer.sanitize(text, false, true);
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/generator/DmnGenerator.java b/dmn-generator/src/main/java/de/uniko/bks/generator/DmnGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..9e38dc75b319053470089342f42877f25e9689e9
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/generator/DmnGenerator.java
@@ -0,0 +1,121 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.generator;
+
+import de.uniko.bks.dom.dmn.Decision;
+import de.uniko.bks.dom.dmn.DecisionTable;
+import de.uniko.bks.dom.dmn.DmnRule;
+import de.uniko.bks.dom.dmn.entry.InputEntry;
+import de.uniko.bks.generator.entry.InputEntryGenerator;
+import de.uniko.bks.generator.entry.OutputEntryGenerator;
+import de.uniko.bks.generator.entry.OutputEntryList;
+import de.uniko.bks.generator.header.InputHeaderGenerator;
+import de.uniko.bks.generator.header.OutputHeaderGenerator;
+import de.uniko.bks.xml.FileHandler;
+import de.uniko.bks.xml.XmlMarshaller;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.UUID;
+import javax.xml.bind.JAXBException;
+
+/** Main class of the generator which supervises the DMN generation */
+public class DmnGenerator {
+  /** Identifier suffix for all ids in the DMN decision */
+  private static String identifier = UUID.randomUUID().toString().substring(0, 4);
+
+  /**
+   * Function which generates a DMN rule list
+   *
+   * @param columnCount Number of columns in the DMN table
+   * @param rowCount Number of rows in the DMN table
+   * @param outputEntryList List of output entries used in the dmn file (note the negations are
+   *     created automatically)
+   * @return The DMN rule list
+   */
+  private static ArrayList<DmnRule> generateDmnRuleList(
+      int columnCount, int rowCount, OutputEntryList outputEntryList) {
+    ArrayList<DmnRule> dmnRuleList = new ArrayList<>();
+    // Generate a rule for each row
+    for (int i = 0; i < rowCount; i++) {
+      DmnRule dmnRule = new DmnRule();
+      dmnRule.setId("dmnRule_" + identifier + "_" + i);
+      // Generate literals for a rule
+      ArrayList<InputEntry> inputEntryList = new ArrayList<>();
+      for (int j = 0; j < columnCount; j++) {
+        inputEntryList.add(InputEntryGenerator.generateInputEntry(identifier, j, i));
+      }
+      dmnRule.setInputEntry(inputEntryList);
+      dmnRule.setOutputEntry(
+          OutputEntryGenerator.generateOutputEntry(identifier, i, outputEntryList));
+      dmnRuleList.add(dmnRule);
+    }
+
+    return dmnRuleList;
+  }
+
+  /**
+   * Function which generates a DMN decsion table
+   *
+   * @param columnCount Number of columns in the DMN table
+   * @param rowCount Number of rows in the DMN table
+   * @param hitPolicy Hit policy for the DMN table
+   * @param outputEntryList List of output entries used in the dmn file (note the negations are
+   *     created automatically)
+   * @return The generated DMN decision table
+   */
+  private static DecisionTable generateDecisionTable(
+      int columnCount, int rowCount, String hitPolicy, OutputEntryList outputEntryList) {
+    DecisionTable decisionTable = new DecisionTable();
+    decisionTable.setId("decisionTable_" + identifier);
+    decisionTable.setHitPolicy(hitPolicy);
+    decisionTable.setInput(InputHeaderGenerator.generateInputList(identifier, columnCount));
+    decisionTable.setOutputHeader(
+        OutputHeaderGenerator.generateOutputHeader(identifier, hitPolicy, outputEntryList));
+    decisionTable.setDmnRule(generateDmnRuleList(columnCount, rowCount, outputEntryList));
+    return decisionTable;
+  }
+
+  /**
+   * Function which generates a DMN file
+   *
+   * @param columnCount Number of columns in the DMN table
+   * @param rowCount Number of rows in the DMN table
+   * @param hitPolicy Hit policy for the DMN table
+   * @param outputEntryList List of output entries used in the dmn file (note the negations are
+   *     created automatically)
+   * @return The path of the newly created file
+   * @throws JAXBException Root exception for all JAXB exceptions
+   * @throws IOException Signals that an I/O exception of some sort has occurred
+   */
+  public static Path generateDmnFile(
+      int columnCount, int rowCount, String hitPolicy, OutputEntryList outputEntryList)
+      throws JAXBException, IOException {
+    Decision decision = new Decision();
+    decision.setId("decision_" + identifier);
+    decision.setName("decision_" + identifier);
+    decision.setDmnTable(generateDecisionTable(columnCount, rowCount, hitPolicy, outputEntryList));
+
+    // Generate the XML fragment
+    System.out.println(
+        "Generating DMN file with "
+            + columnCount
+            + " columns, "
+            + rowCount
+            + " rows and the "
+            + hitPolicy
+            + " hit policy");
+    String xmlResult = XmlMarshaller.marshalDmnTable(decision);
+    // Get the template for an empty DMN model
+    String dmnTemplate = FileHandler.read("EmptyDmn.xml");
+    // Replace the placeholder with the generated content
+    String fileContent = dmnTemplate.replace("<!--replace-me-->", xmlResult);
+    // Write the content into a new file
+    Path filePath = FileHandler.write(identifier, columnCount, rowCount, hitPolicy, fileContent);
+    System.out.println("Created new DMN file successfully with the path " + filePath.toString());
+    return filePath;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/generator/entry/InputEntryGenerator.java b/dmn-generator/src/main/java/de/uniko/bks/generator/entry/InputEntryGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..ecc1b7159995d24b52b612db7593003facb59b47
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/generator/entry/InputEntryGenerator.java
@@ -0,0 +1,47 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.generator.entry;
+
+import de.uniko.bks.dom.dmn.entry.InputEntry;
+import java.util.Random;
+
+/** Class which generates a single input entry for the DMN */
+public class InputEntryGenerator {
+
+  private static String generateInputRange() {
+    String out = "";
+    if (new Random().nextInt(1000) < 10) {
+      out += new Random().nextBoolean() ? "<" : "<=";
+      out += new Random().nextInt(1500) - 1000;
+    } else if (new Random().nextInt(1000) < 10) {
+      out += new Random().nextBoolean() ? ">" : "=";
+      out += new Random().nextInt(1500) + 50;
+    } else {
+      // Value between 0 and 15
+      int lowerLimit = new Random().nextInt(2000) - 1500;
+      // Value between 15 and 45
+      int upperLimit = lowerLimit + new Random().nextInt(1000) + 20;
+
+      out += new Random().nextBoolean() ? "[" : "]";
+      out += lowerLimit + ".." + upperLimit;
+      out += new Random().nextBoolean() ? "[" : "]";
+    }
+    return out;
+  }
+
+  /**
+   * Function which generates an integer input entry range
+   *
+   * @param identifier Identifier suffix for all ids in the DMN decision
+   * @param columnCount Number of the current column which is created
+   * @param rowCount Number of the current row which is created
+   * @return The generated input entry
+   */
+  public static InputEntry generateInputEntry(String identifier, int columnCount, int rowCount) {
+    return new InputEntry(
+        "inputEntry_" + identifier + "_" + rowCount + "_" + columnCount, generateInputRange());
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/generator/entry/OutputEntryGenerator.java b/dmn-generator/src/main/java/de/uniko/bks/generator/entry/OutputEntryGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..36d32d44c13550024737f46baf60a6175c503ea6
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/generator/entry/OutputEntryGenerator.java
@@ -0,0 +1,46 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.generator.entry;
+
+import de.uniko.bks.dom.dmn.entry.OutputEntry;
+import java.util.Random;
+
+/** Class which generates a single output entry for the DMN */
+public class OutputEntryGenerator {
+  /**
+   * Function which negates a given value
+   *
+   * @param outputEntry Value which should be negated
+   * @return THe negated value
+   */
+  private static String negateOutputEntry(String outputEntry) {
+    return "not(" + outputEntry + ")";
+  }
+
+  /**
+   * Function which generates a random output entry using the items from the OutputEntryList
+   *
+   * @param identifier Identifier suffix for all ids in the DMN decision
+   * @param rowCount Number of the current row which is created
+   * @param outputEntryList List of output entries used in the dmn file (note the negations are
+   *     created automatically)
+   * @return A random output entry
+   */
+  public static OutputEntry generateOutputEntry(
+      String identifier, int rowCount, OutputEntryList outputEntryList) {
+    OutputEntry outputEntry = new OutputEntry();
+    outputEntry.setId("outputEntry_" + identifier + "_" + rowCount);
+    String outputEntryValue = outputEntryList.getRandomValue();
+    // Check if the value should be negated or not
+    if (new Random().nextBoolean()) {
+      //  outputEntryValue = negateOutputEntry(outputEntryValue);
+    }
+
+    // Set the value of the output entry
+    outputEntry.setText(outputEntryValue);
+    return outputEntry;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/generator/entry/OutputEntryList.java b/dmn-generator/src/main/java/de/uniko/bks/generator/entry/OutputEntryList.java
new file mode 100644
index 0000000000000000000000000000000000000000..cd685ea516a6e1a3b0b2433706f6d0a034126409
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/generator/entry/OutputEntryList.java
@@ -0,0 +1,35 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.generator.entry;
+
+import java.util.Random;
+
+public class OutputEntryList {
+  /** The array containing the output values */
+  private String[] values = {"a", "b", "c", "d", "e", "f", "g", "h"};
+
+  public String[] getValues() {
+    return this.values;
+  }
+
+  public void setValues(String[] values) {
+    // Check if the given outputEntryList is empty
+    if (values != null && values.length > 0) {
+      // Set the list from the parameter
+      this.values = values;
+    }
+  }
+
+  /**
+   * Function which gets one random item of the values array
+   *
+   * @return The random array entry
+   */
+  String getRandomValue() {
+    int randomIndex = new Random().nextInt(this.values.length);
+    return this.values[randomIndex];
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/generator/header/InputHeaderGenerator.java b/dmn-generator/src/main/java/de/uniko/bks/generator/header/InputHeaderGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..7ead4340e33dde93b65b9185204263de1ff9783e
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/generator/header/InputHeaderGenerator.java
@@ -0,0 +1,41 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.generator.header;
+
+import de.uniko.bks.dom.dfl.rule.RuleType;
+import de.uniko.bks.dom.dmn.Input;
+import de.uniko.bks.dom.dmn.header.InputHeader;
+import java.util.ArrayList;
+
+/** Class which generates a list of input headers for the DMN */
+public class InputHeaderGenerator {
+  /**
+   * Function which generates the input list (list of input headers)
+   *
+   * @param identifier Identifier suffix for all ids in the DMN decision
+   * @param columnCount Number of columns in the DMN table
+   * @return The generated input list
+   */
+  public static ArrayList<Input> generateInputList(String identifier, int columnCount) {
+    ArrayList<Input> inputList = new ArrayList<>();
+    // Generate an integer input header for each column
+    for (int i = 0; i < columnCount; i++) {
+      Input input = new Input();
+      input.setId("input_" + identifier + "_" + i);
+      input.setLabel("input_" + identifier + "_" + i);
+      // Create a new input header
+      InputHeader inputHeader =
+          new InputHeader(
+              "inputHeader_" + identifier + "_" + i,
+              RuleType.INT.getValue(),
+              "inputHeader_" + identifier + "_" + i);
+      input.setInputHeader(inputHeader);
+      inputList.add(input);
+    }
+
+    return inputList;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/generator/header/OutputHeaderGenerator.java b/dmn-generator/src/main/java/de/uniko/bks/generator/header/OutputHeaderGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..11ce7a3395b868c172e2a5a9fe9be20ff2d81470
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/generator/header/OutputHeaderGenerator.java
@@ -0,0 +1,48 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.generator.header;
+
+import de.uniko.bks.dom.dfl.rule.RuleType;
+import de.uniko.bks.dom.dmn.HitPolicy;
+import de.uniko.bks.dom.dmn.header.OutputHeader;
+import de.uniko.bks.dom.dmn.header.OutputValues;
+import de.uniko.bks.generator.entry.OutputEntryList;
+
+/** Class which generates a single output header for the DMN */
+public class OutputHeaderGenerator {
+  /**
+   * Function which generates a DMN output header
+   *
+   * @param identifier Identifier suffix for all ids in the DMN decision
+   * @param hitPolicy The HitPolicy of the table
+   * @param outputEntryList List of output entries used in the dmn file (note the negations are
+   *     created automatically)
+   * @return The DMN output header
+   */
+  public static OutputHeader generateOutputHeader(
+      String identifier, String hitPolicy, OutputEntryList outputEntryList) {
+    OutputHeader outputHeader = new OutputHeader();
+    outputHeader.setId("output_" + identifier);
+    outputHeader.setType(RuleType.STRING.getValue());
+    outputHeader.setText("output_" + identifier);
+    // Set the rule order if it is needed
+    if (hitPolicy.equals(HitPolicy.PRIORITY.getValue())
+        || hitPolicy.equals(HitPolicy.OUTPUT_ORDER.getValue())) {
+      StringBuilder stringBuilder = new StringBuilder();
+      for (int i = 0; i < outputEntryList.getValues().length; i++) {
+        stringBuilder.append("\"");
+        stringBuilder.append(outputEntryList.getValues()[i]);
+        stringBuilder.append("\"");
+        // Check if it is the last item
+        if (i < outputEntryList.getValues().length - 1) {
+          stringBuilder.append(",");
+        }
+      }
+      outputHeader.setOutputValues(new OutputValues(identifier, stringBuilder.toString()));
+    }
+    return outputHeader;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/statistic/DmnDate.java b/dmn-generator/src/main/java/de/uniko/bks/statistic/DmnDate.java
new file mode 100644
index 0000000000000000000000000000000000000000..18068b8e56f8679e147bddf7f4d3b4560c4640e5
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/statistic/DmnDate.java
@@ -0,0 +1,161 @@
+package de.uniko.bks.statistic;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+class DmnDate {
+
+  private Date date;
+  private Date endDate;
+  private boolean isLowerThan = false;
+  private boolean isGreaterThan = false;
+  private boolean itDoesntMatter = false;
+
+  boolean isItDoesntMatter() {
+    return itDoesntMatter;
+  }
+
+  private Date getDate() {
+    return date;
+  }
+
+  private Date getEndDate() {
+    return endDate;
+  }
+
+  private boolean isLowerThan() {
+    return isLowerThan;
+  }
+
+  private boolean isGreaterThan() {
+    return isGreaterThan;
+  }
+
+  private boolean isRange() {
+    return isRange;
+  }
+
+  private boolean isRange = false;
+
+  DmnDate(String dateString) {
+    parseString(dateString);
+  }
+
+  private void parseString(String dateString) {
+    if (dateString.length() == 0) {
+      this.itDoesntMatter = true;
+    } else {
+      String first = dateString.substring(0, 1);
+      if (first.contains("[")) {
+        isRange = true;
+        dateString = dateString.replace("..", "#");
+        String modDateString = dateString;
+        modDateString = modDateString.replace("[", "");
+        modDateString = modDateString.replace("]", "");
+        String[] dates = modDateString.split("#");
+        this.date = parseStringToDate(dates[0]);
+        this.endDate = parseStringToDate(dates[1]);
+      } else {
+        if (dateString.contains("&lt;") || dateString.contains("<")) {
+          dateString = dateString.replace("&lt;", "");
+          dateString = dateString.replace("<", "");
+          this.isLowerThan = true;
+        }
+        if (dateString.contains("&gt;") || dateString.contains(">")) {
+          dateString = dateString.replace("&gt;", "");
+          dateString = dateString.replace(">", "");
+          this.isGreaterThan = true;
+        }
+        this.date = parseStringToDate(dateString);
+        this.endDate = this.date;
+      }
+    }
+  }
+
+  private Date parseStringToDate(String dateString) {
+    SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+    dateString = dateString.replace("date and time(\"", "");
+    dateString = dateString.replace("\")", "");
+    dateString = dateString.replace(" ", "");
+    Date date1;
+    try {
+      date1 = parser.parse(dateString);
+      return date1;
+    } catch (ParseException e) {
+      date1 = new Date();
+      e.printStackTrace();
+      return date1;
+    }
+  }
+
+  boolean isOverlapping(DmnDate dateToCheck) {
+    if (this.itDoesntMatter || dateToCheck.isItDoesntMatter()) {
+      return true;
+    }
+    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+    if (this.isRange) {
+      if (dateToCheck.isRange) {
+        if ((this.date.after(dateToCheck.getDate()) && this.date.before(dateToCheck.getEndDate()))
+            || (this.endDate.after(dateToCheck.getDate())
+                && this.endDate.before(dateToCheck.getEndDate()))
+            || (dateToCheck.getDate().after(this.date)
+                && dateToCheck.getDate().before(this.endDate))
+            || (dateToCheck.getEndDate().after(this.date)
+                && dateToCheck.getEndDate().before(this.endDate))) {
+          return true;
+        }
+      }
+      if (dateToCheck.isLowerThan()) {
+        if (this.date.before(dateToCheck.getDate())) {
+          return true;
+        }
+      } else if (dateToCheck.isGreaterThan()) {
+        if (this.endDate.after(dateToCheck.getDate())) {
+          return true;
+        }
+      }
+      if (dateToCheck.getDate().after(this.date) && dateToCheck.getDate().before(this.endDate)) {
+        return true;
+      }
+    } else if (this.isLowerThan) {
+      if (dateToCheck.isRange()) {
+        if (dateToCheck.date.before(this.date)) {
+          return true;
+        }
+      }
+      if (dateToCheck.isLowerThan()) {
+        if ((this.date.before(dateToCheck.getDate()))
+            || (dateToCheck.getDate().before(this.date))) {
+          return true;
+        }
+      } else if (dateToCheck.isGreaterThan()) {
+        if ((this.date.after(dateToCheck.getDate())) || (dateToCheck.getDate().before(this.date))) {
+          return true;
+        }
+      }
+      if (dateToCheck.getDate().before(this.date)) {
+        return true;
+      }
+    } else if (this.isGreaterThan()) {
+      if (dateToCheck.isRange()) {
+        if (dateToCheck.endDate.after(this.date)) {
+          return true;
+        }
+      }
+      if (dateToCheck.isLowerThan()) {
+        if ((this.date.before(dateToCheck.getDate())) || (dateToCheck.getDate().after(this.date))) {
+          return true;
+        }
+      } else if (dateToCheck.isGreaterThan()) {
+        if ((this.date.after(dateToCheck.getDate())) || (dateToCheck.getDate().after(this.date))) {
+          return true;
+        }
+      }
+      if (dateToCheck.getDate().after(this.date)) {
+        return true;
+      }
+    }
+    return format.format(this.date).equals(format.format(dateToCheck.getDate()));
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/statistic/DmnFile.java b/dmn-generator/src/main/java/de/uniko/bks/statistic/DmnFile.java
new file mode 100644
index 0000000000000000000000000000000000000000..356810368d5cc8065d7706a3d08fd9896dfe8f22
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/statistic/DmnFile.java
@@ -0,0 +1,43 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.statistic;
+
+import java.nio.file.Path;
+
+/** Class wrapping meta information about a generated DMN file */
+public class DmnFile {
+  /** HitPolicy of the DMN file */
+  private String hitPolicy;
+  /** Path where the file is located */
+  private Path path;
+  /** Number of columns in the DMN table */
+  private int columnCount;
+  /** Number of the rows in the DMN table */
+  private int rowCount;
+
+  public DmnFile(String hitPolicy, Path path, int columnCount, int rowCount) {
+    this.hitPolicy = hitPolicy;
+    this.path = path;
+    this.columnCount = columnCount;
+    this.rowCount = rowCount;
+  }
+
+  public String getHitPolicy() {
+    return hitPolicy;
+  }
+
+  public Path getPath() {
+    return path;
+  }
+
+  public int getColumnCount() {
+    return columnCount;
+  }
+
+  public int getRowCount() {
+    return rowCount;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/statistic/NumberLine.java b/dmn-generator/src/main/java/de/uniko/bks/statistic/NumberLine.java
new file mode 100644
index 0000000000000000000000000000000000000000..347f12ec867d474800152af7a2b70363f8014a34
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/statistic/NumberLine.java
@@ -0,0 +1,191 @@
+package de.uniko.bks.statistic;
+
+import com.google.common.collect.Multimap;
+import com.google.common.collect.MultimapBuilder;
+import java.util.*;
+
+public class NumberLine {
+  private ArrayList<Map<Integer, Set<dmnInt>>> line = new ArrayList<>();
+  private Set<Integer> isInLine = new HashSet<>();
+  private Set<dmnInt> beginning = new HashSet<>();
+  private Set<dmnInt> end = new HashSet<>();
+  private Set<dmnInt> all = new HashSet<>();
+  private Map<dmnInt, Set<dmnInt>> numberOverlaps = new HashMap<>();
+  private boolean somethingChanged = false;
+  private boolean overlapsAreComputed = false;
+  private Set<dmnInt> forSureOverlaps = new HashSet<>();
+
+  private Map<dmnInt, String> mapping = new HashMap<>();
+
+  public ArrayList<Map<Integer, Set<dmnInt>>> getLine() {
+    return line;
+  }
+
+  public Set<dmnInt> computeOverlapping(dmnInt number, Set<dmnInt> setToCompute) {
+    HashSet<dmnInt> result = new HashSet<>();
+    for (dmnInt numberToCheck : setToCompute) {
+      if (number.compare(numberToCheck)) {
+        result.add(numberToCheck);
+      }
+    }
+    return result;
+  }
+
+  public Set<Set<String>> getRuleOverlaps() {
+    Set<Set<String>> result = new HashSet<>();
+    if (somethingChanged || !overlapsAreComputed) {
+      numberOverlaps = getOverlappingNumbers();
+    }
+    for (dmnInt number : numberOverlaps.keySet()) {
+      String numberRule = mapping.get(number);
+      for (dmnInt overlapNumber : numberOverlaps.get(number)) {
+        HashSet<String> overlap = new HashSet<>();
+        overlap.add(numberRule);
+        overlap.add(mapping.get(overlapNumber));
+        result.add(overlap);
+      }
+    }
+    return result;
+  }
+
+  public Set<Set<String>> getRuleOverlaps(Set<Set<String>> currentIncons) {
+    Set<Set<String>> result = getRuleOverlaps();
+    result.retainAll(currentIncons);
+    return result;
+  }
+
+  public Map<dmnInt, Set<dmnInt>> getOverlappingNumbers() {
+    HashSet<dmnInt> allBefore = new HashSet<>();
+    HashSet<dmnInt> allAfter = new HashSet<>(all);
+    Multimap<dmnInt, dmnInt> numbersToProcess = MultimapBuilder.hashKeys().hashSetValues().build();
+    Map<dmnInt, Set<dmnInt>> result = new HashMap<>();
+
+    Iterator<Map<Integer, Set<dmnInt>>> iter = line.iterator();
+    while (iter.hasNext()) {
+      Map<Integer, Set<dmnInt>> currentmap = iter.next();
+      if (currentmap.size() != 1) {
+        System.out.println("something went wrong");
+        continue;
+      }
+      allAfter.removeAll(currentmap.get(currentmap.keySet().iterator().next()));
+      for (dmnInt currentNumber : currentmap.get(currentmap.keySet().iterator().next())) {
+
+        if (currentNumber.isDoesntMatter()) {
+          HashSet<dmnInt> allMinusItself = new HashSet<>(all);
+          allMinusItself.remove(currentNumber);
+          result.put(currentNumber, allMinusItself);
+          continue;
+        }
+        HashSet<dmnInt> forCurrentNumber = new HashSet<>();
+        forCurrentNumber.addAll(
+            computeOverlapping(
+                currentNumber, currentmap.get(currentmap.keySet().iterator().next())));
+        forCurrentNumber.addAll(forSureOverlaps);
+        if (currentNumber.isRange()) {
+          if ((numbersToProcess).containsKey(currentNumber)) {
+            forCurrentNumber.addAll(numbersToProcess.get(currentNumber));
+            numbersToProcess.removeAll(currentmap);
+          } else {
+            computeOverlapping(currentNumber, currentmap.get(currentmap.keySet().iterator().next()))
+                .forEach(number -> numbersToProcess.put(currentNumber, number));
+          }
+        }
+        if (currentNumber.isLower()) {
+          forCurrentNumber.addAll(allBefore);
+          forCurrentNumber.addAll(beginning);
+        }
+        if (currentNumber.isGreater()) {
+          forCurrentNumber.addAll(allAfter);
+          forCurrentNumber.addAll(end);
+        }
+        if (!forCurrentNumber.isEmpty()) {
+          if (forCurrentNumber.contains(currentNumber)) {
+            forCurrentNumber.remove(currentNumber);
+          }
+          result.put(currentNumber, forCurrentNumber);
+        }
+      }
+      allBefore.addAll(currentmap.get(currentmap.keySet().iterator().next()));
+      numbersToProcess
+          .keySet()
+          .forEach(
+              key ->
+                  numbersToProcess.putAll(
+                      key, currentmap.get(currentmap.keySet().iterator().next())));
+    }
+    numberOverlaps = result;
+    somethingChanged = false;
+    overlapsAreComputed = true;
+    return result;
+  }
+
+  public void addToLine(dmnInt number, String ruleName) {
+    somethingChanged = true;
+    mapping.put(number, ruleName);
+    all.add(number);
+    number.setRuleName(ruleName);
+    if (number.isDoesntMatter()) {
+      forSureOverlaps.add(number);
+      return;
+    }
+
+    if (number.isRange()) {
+      addToLine(number.getLowerBoundInt(), number);
+      addToLine(number.getUpperBoundInt(), number);
+      return;
+    }
+    if (number.isLower()) {
+      beginning.add(number);
+    }
+    if (number.isGreater()) {
+      end.add(number);
+    }
+    addToLine(number.getNumberInt(), number);
+  }
+
+  private void addToLine(Integer number, dmnInt num) {
+    if (line.isEmpty()) {
+      Set<dmnInt> currentSet = new HashSet<>();
+      currentSet.add(num);
+      Map<Integer, Set<dmnInt>> newMap = new HashMap<>();
+      newMap.put(number, currentSet);
+      line.add(newMap);
+    }
+    ArrayList<Map<Integer, Set<dmnInt>>> newLine = new ArrayList<>(line);
+    Iterator<Map<Integer, Set<dmnInt>>> iter = newLine.iterator();
+
+    while (iter.hasNext()) {
+      Map<Integer, Set<dmnInt>> currentmap = iter.next();
+      if (currentmap.size() != 1) {
+        System.out.println("something went wrong");
+        continue;
+      }
+      int currentNumber = currentmap.keySet().iterator().next();
+      if (number < currentNumber) {
+        Set<dmnInt> currentSet = new HashSet<>();
+        currentSet.add(num);
+        Map<Integer, Set<dmnInt>> newMap = new HashMap<>();
+        newMap.put(number, currentSet);
+        int index = line.indexOf(currentmap);
+        line.add(index, newMap);
+      } else if (number == currentNumber) {
+        Set<dmnInt> currentSet = currentmap.get(number);
+        currentSet.add(num);
+        Map<Integer, Set<dmnInt>> newMap = new HashMap<>();
+        newMap.put(number, currentSet);
+        int index = line.indexOf(currentmap);
+        line.remove(currentmap);
+        line.add(index, newMap);
+        break;
+      } else if ((number > currentNumber) && iter.hasNext()) {
+        continue;
+      } else if (!iter.hasNext()) {
+        Set<dmnInt> currentSet = new HashSet<>();
+        currentSet.add(num);
+        Map<Integer, Set<dmnInt>> newMap = new HashMap<>();
+        newMap.put(number, currentSet);
+        line.add(newMap);
+      }
+    }
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/statistic/NumberLineDouble.java b/dmn-generator/src/main/java/de/uniko/bks/statistic/NumberLineDouble.java
new file mode 100644
index 0000000000000000000000000000000000000000..92eeffc29630a3a49e1b01578a1e4b039f3cf749
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/statistic/NumberLineDouble.java
@@ -0,0 +1,185 @@
+package de.uniko.bks.statistic;
+
+import com.google.common.collect.Multimap;
+import com.google.common.collect.MultimapBuilder;
+import java.util.*;
+
+public class NumberLineDouble {
+  private ArrayList<Map<Double, Set<dmnInt>>> line = new ArrayList<>();
+  private Set<Double> isInLine = new HashSet<>();
+  private Set<dmnInt> beginning = new HashSet<>();
+  private Set<dmnInt> end = new HashSet<>();
+  private Set<dmnInt> all = new HashSet<>();
+  private Map<dmnInt, Set<dmnInt>> numberOverlaps = new HashMap<>();
+  private boolean somethingChanged = false;
+  private boolean overlapsAreComputed = false;
+  private Set<dmnInt> forSureOverlaps = new HashSet<>();
+
+  private Map<dmnInt, String> mapping = new HashMap<>();
+
+  public ArrayList<Map<Double, Set<dmnInt>>> getLine() {
+    return line;
+  }
+
+  public Set<dmnInt> computeOverlapping(dmnInt number, Set<dmnInt> setToCompute) {
+    HashSet<dmnInt> result = new HashSet<>();
+    for (dmnInt numberToCheck : setToCompute) {
+      if (number.compare(numberToCheck)) {
+        result.add(numberToCheck);
+      }
+    }
+    return result;
+  }
+
+  public Set<Set<String>> getRuleOverlaps() {
+    Set<Set<String>> result = new HashSet<>();
+    if (somethingChanged || !overlapsAreComputed) {
+      numberOverlaps = getOverlappingNumbers();
+    }
+    for (dmnInt number : numberOverlaps.keySet()) {
+      String numberRule = mapping.get(number);
+      for (dmnInt overlapNumber : numberOverlaps.get(number)) {
+        HashSet<String> overlap = new HashSet<>();
+        overlap.add(numberRule);
+        overlap.add(mapping.get(overlapNumber));
+        result.add(overlap);
+      }
+    }
+    return result;
+  }
+
+  public Map<dmnInt, Set<dmnInt>> getOverlappingNumbers() {
+    HashSet<dmnInt> allBefore = new HashSet<>();
+    HashSet<dmnInt> allAfter = new HashSet<>(all);
+    Multimap<dmnInt, dmnInt> numbersToProcess = MultimapBuilder.hashKeys().hashSetValues().build();
+    Map<dmnInt, Set<dmnInt>> result = new HashMap<>();
+
+    Iterator<Map<Double, Set<dmnInt>>> iter = line.iterator();
+    while (iter.hasNext()) {
+      Map<Double, Set<dmnInt>> currentmap = iter.next();
+      if (currentmap.size() != 1) {
+        System.out.println("something went wrong");
+        continue;
+      }
+      allAfter.removeAll(currentmap.get(currentmap.keySet().iterator().next()));
+      for (dmnInt currentNumber : currentmap.get(currentmap.keySet().iterator().next())) {
+
+        if (currentNumber.isDoesntMatter()) {
+          HashSet<dmnInt> allMinusItself = new HashSet<>(all);
+          allMinusItself.remove(currentNumber);
+          result.put(currentNumber, allMinusItself);
+          continue;
+        }
+        HashSet<dmnInt> forCurrentNumber = new HashSet<>();
+        forCurrentNumber.addAll(
+            computeOverlapping(
+                currentNumber, currentmap.get(currentmap.keySet().iterator().next())));
+        forCurrentNumber.addAll(forSureOverlaps);
+        if (currentNumber.isRange()) {
+          if ((numbersToProcess).containsKey(currentNumber)) {
+            forCurrentNumber.addAll(numbersToProcess.get(currentNumber));
+            numbersToProcess.removeAll(currentmap);
+          } else {
+            computeOverlapping(currentNumber, currentmap.get(currentmap.keySet().iterator().next()))
+                .forEach(number -> numbersToProcess.put(currentNumber, number));
+          }
+        }
+        if (currentNumber.isLower()) {
+          forCurrentNumber.addAll(allBefore);
+          forCurrentNumber.addAll(beginning);
+        }
+        if (currentNumber.isGreater()) {
+          forCurrentNumber.addAll(allAfter);
+          forCurrentNumber.addAll(end);
+        }
+        if (!forCurrentNumber.isEmpty()) {
+          if (forCurrentNumber.contains(currentNumber)) {
+            forCurrentNumber.remove(currentNumber);
+          }
+          result.put(currentNumber, forCurrentNumber);
+        }
+      }
+      allBefore.addAll(currentmap.get(currentmap.keySet().iterator().next()));
+      numbersToProcess
+          .keySet()
+          .forEach(
+              key ->
+                  numbersToProcess.putAll(
+                      key, currentmap.get(currentmap.keySet().iterator().next())));
+    }
+    numberOverlaps = result;
+    somethingChanged = false;
+    overlapsAreComputed = true;
+    return result;
+  }
+
+  public void addToLine(dmnInt number, String ruleName) {
+    somethingChanged = true;
+    mapping.put(number, ruleName);
+    all.add(number);
+    number.setRuleName(ruleName);
+    if (number.isDoesntMatter()) {
+      forSureOverlaps.add(number);
+      return;
+    }
+
+    if (number.isRange()) {
+      addToLine(number.getLowerBoundDouble(), number);
+      addToLine(number.getUpperBoundDouble(), number);
+      return;
+    }
+    if (number.isLower()) {
+      beginning.add(number);
+    }
+    if (number.isGreater()) {
+      end.add(number);
+    }
+    addToLine(number.getNumberDouble(), number);
+  }
+
+  private void addToLine(Double number, dmnInt num) {
+    if (line.isEmpty()) {
+      Set<dmnInt> currentSet = new HashSet<>();
+      currentSet.add(num);
+      Map<Double, Set<dmnInt>> newMap = new HashMap<>();
+      newMap.put(number, currentSet);
+      line.add(newMap);
+    }
+    ArrayList<Map<Double, Set<dmnInt>>> newLine = new ArrayList<>(line);
+    Iterator<Map<Double, Set<dmnInt>>> iter = newLine.iterator();
+
+    while (iter.hasNext()) {
+      Map<Double, Set<dmnInt>> currentmap = iter.next();
+      if (currentmap.size() != 1) {
+        System.out.println("something went wrong");
+        continue;
+      }
+      double currentNumber = currentmap.keySet().iterator().next();
+      if (number < currentNumber) {
+        Set<dmnInt> currentSet = new HashSet<>();
+        currentSet.add(num);
+        Map<Double, Set<dmnInt>> newMap = new HashMap<>();
+        newMap.put(number, currentSet);
+        int index = line.indexOf(currentmap);
+        line.add(index, newMap);
+      } else if (number == currentNumber) {
+        Set<dmnInt> currentSet = currentmap.get(number);
+        currentSet.add(num);
+        Map<Double, Set<dmnInt>> newMap = new HashMap<>();
+        newMap.put(number, currentSet);
+        int index = line.indexOf(currentmap);
+        line.remove(currentmap);
+        line.add(index, newMap);
+        break;
+      } else if ((number > currentNumber) && iter.hasNext()) {
+        continue;
+      } else if (!iter.hasNext()) {
+        Set<dmnInt> currentSet = new HashSet<>();
+        currentSet.add(num);
+        Map<Double, Set<dmnInt>> newMap = new HashMap<>();
+        newMap.put(number, currentSet);
+        line.add(newMap);
+      }
+    }
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/statistic/NumberLineLong.java b/dmn-generator/src/main/java/de/uniko/bks/statistic/NumberLineLong.java
new file mode 100644
index 0000000000000000000000000000000000000000..36863b4434d599ff02c1f708bed93b230098946b
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/statistic/NumberLineLong.java
@@ -0,0 +1,185 @@
+package de.uniko.bks.statistic;
+
+import com.google.common.collect.Multimap;
+import com.google.common.collect.MultimapBuilder;
+import java.util.*;
+
+public class NumberLineLong {
+  private ArrayList<Map<Long, Set<dmnInt>>> line = new ArrayList<>();
+  private Set<Long> isInLine = new HashSet<>();
+  private Set<dmnInt> beginning = new HashSet<>();
+  private Set<dmnInt> end = new HashSet<>();
+  private Set<dmnInt> all = new HashSet<>();
+  private Map<dmnInt, Set<dmnInt>> numberOverlaps = new HashMap<>();
+  private boolean somethingChanged = false;
+  private boolean overlapsAreComputed = false;
+  private Set<dmnInt> forSureOverlaps = new HashSet<>();
+
+  private Map<dmnInt, String> mapping = new HashMap<>();
+
+  public ArrayList<Map<Long, Set<dmnInt>>> getLine() {
+    return line;
+  }
+
+  public Set<dmnInt> computeOverlapping(dmnInt number, Set<dmnInt> setToCompute) {
+    HashSet<dmnInt> result = new HashSet<>();
+    for (dmnInt numberToCheck : setToCompute) {
+      if (number.compare(numberToCheck)) {
+        result.add(numberToCheck);
+      }
+    }
+    return result;
+  }
+
+  public Set<Set<String>> getRuleOverlaps() {
+    Set<Set<String>> result = new HashSet<>();
+    if (somethingChanged || !overlapsAreComputed) {
+      numberOverlaps = getOverlappingNumbers();
+    }
+    for (dmnInt number : numberOverlaps.keySet()) {
+      String numberRule = mapping.get(number);
+      for (dmnInt overlapNumber : numberOverlaps.get(number)) {
+        HashSet<String> overlap = new HashSet<>();
+        overlap.add(numberRule);
+        overlap.add(mapping.get(overlapNumber));
+        result.add(overlap);
+      }
+    }
+    return result;
+  }
+
+  public Map<dmnInt, Set<dmnInt>> getOverlappingNumbers() {
+    HashSet<dmnInt> allBefore = new HashSet<>();
+    HashSet<dmnInt> allAfter = new HashSet<>(all);
+    Multimap<dmnInt, dmnInt> numbersToProcess = MultimapBuilder.hashKeys().hashSetValues().build();
+    Map<dmnInt, Set<dmnInt>> result = new HashMap<>();
+
+    Iterator<Map<Long, Set<dmnInt>>> iter = line.iterator();
+    while (iter.hasNext()) {
+      Map<Long, Set<dmnInt>> currentmap = iter.next();
+      if (currentmap.size() != 1) {
+        System.out.println("something went wrong");
+        continue;
+      }
+      allAfter.removeAll(currentmap.get(currentmap.keySet().iterator().next()));
+      for (dmnInt currentNumber : currentmap.get(currentmap.keySet().iterator().next())) {
+
+        if (currentNumber.isDoesntMatter()) {
+          HashSet<dmnInt> allMinusItself = new HashSet<>(all);
+          allMinusItself.remove(currentNumber);
+          result.put(currentNumber, allMinusItself);
+          continue;
+        }
+        HashSet<dmnInt> forCurrentNumber = new HashSet<>();
+        forCurrentNumber.addAll(
+            computeOverlapping(
+                currentNumber, currentmap.get(currentmap.keySet().iterator().next())));
+        forCurrentNumber.addAll(forSureOverlaps);
+        if (currentNumber.isRange()) {
+          if ((numbersToProcess).containsKey(currentNumber)) {
+            forCurrentNumber.addAll(numbersToProcess.get(currentNumber));
+            numbersToProcess.removeAll(currentmap);
+          } else {
+            computeOverlapping(currentNumber, currentmap.get(currentmap.keySet().iterator().next()))
+                .forEach(number -> numbersToProcess.put(currentNumber, number));
+          }
+        }
+        if (currentNumber.isLower()) {
+          forCurrentNumber.addAll(allBefore);
+          forCurrentNumber.addAll(beginning);
+        }
+        if (currentNumber.isGreater()) {
+          forCurrentNumber.addAll(allAfter);
+          forCurrentNumber.addAll(end);
+        }
+        if (!forCurrentNumber.isEmpty()) {
+          if (forCurrentNumber.contains(currentNumber)) {
+            forCurrentNumber.remove(currentNumber);
+          }
+          result.put(currentNumber, forCurrentNumber);
+        }
+      }
+      allBefore.addAll(currentmap.get(currentmap.keySet().iterator().next()));
+      numbersToProcess
+          .keySet()
+          .forEach(
+              key ->
+                  numbersToProcess.putAll(
+                      key, currentmap.get(currentmap.keySet().iterator().next())));
+    }
+    numberOverlaps = result;
+    somethingChanged = false;
+    overlapsAreComputed = true;
+    return result;
+  }
+
+  public void addToLine(dmnInt number, String ruleName) {
+    somethingChanged = true;
+    mapping.put(number, ruleName);
+    all.add(number);
+    number.setRuleName(ruleName);
+    if (number.isDoesntMatter()) {
+      forSureOverlaps.add(number);
+      return;
+    }
+
+    if (number.isRange()) {
+      addToLine(number.getLowerBoundLong(), number);
+      addToLine(number.getUpperBoundLong(), number);
+      return;
+    }
+    if (number.isLower()) {
+      beginning.add(number);
+    }
+    if (number.isGreater()) {
+      end.add(number);
+    }
+    addToLine(number.getNumberLong(), number);
+  }
+
+  private void addToLine(Long number, dmnInt num) {
+    if (line.isEmpty()) {
+      Set<dmnInt> currentSet = new HashSet<>();
+      currentSet.add(num);
+      Map<Long, Set<dmnInt>> newMap = new HashMap<>();
+      newMap.put(number, currentSet);
+      line.add(newMap);
+    }
+    ArrayList<Map<Long, Set<dmnInt>>> newLine = new ArrayList<>(line);
+    Iterator<Map<Long, Set<dmnInt>>> iter = newLine.iterator();
+
+    while (iter.hasNext()) {
+      Map<Long, Set<dmnInt>> currentmap = iter.next();
+      if (currentmap.size() != 1) {
+        System.out.println("something went wrong");
+        continue;
+      }
+      long currentNumber = currentmap.keySet().iterator().next();
+      if (number < currentNumber) {
+        Set<dmnInt> currentSet = new HashSet<>();
+        currentSet.add(num);
+        Map<Long, Set<dmnInt>> newMap = new HashMap<>();
+        newMap.put(number, currentSet);
+        int index = line.indexOf(currentmap);
+        line.add(index, newMap);
+      } else if (number == currentNumber) {
+        Set<dmnInt> currentSet = currentmap.get(number);
+        currentSet.add(num);
+        Map<Long, Set<dmnInt>> newMap = new HashMap<>();
+        newMap.put(number, currentSet);
+        int index = line.indexOf(currentmap);
+        line.remove(currentmap);
+        line.add(index, newMap);
+        break;
+      } else if ((number > currentNumber) && iter.hasNext()) {
+        continue;
+      } else if (!iter.hasNext()) {
+        Set<dmnInt> currentSet = new HashSet<>();
+        currentSet.add(num);
+        Map<Long, Set<dmnInt>> newMap = new HashMap<>();
+        newMap.put(number, currentSet);
+        line.add(newMap);
+      }
+    }
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/statistic/ParserStatistic.java b/dmn-generator/src/main/java/de/uniko/bks/statistic/ParserStatistic.java
new file mode 100644
index 0000000000000000000000000000000000000000..a9071d88db0e3a8277e397706ae8a9e6c43a92d4
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/statistic/ParserStatistic.java
@@ -0,0 +1,52 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.statistic;
+
+/** Class representing a single statistic item */
+public class ParserStatistic {
+  private String hitPolicy;
+  private int columnCount;
+  private int rowCount;
+  private double averageRunTime;
+
+  public ParserStatistic(String hitPolicy, int columnCount, int rowCount, double averageRunTime) {
+    this.hitPolicy = hitPolicy;
+    this.columnCount = columnCount;
+    this.rowCount = rowCount;
+    this.averageRunTime = averageRunTime;
+  }
+
+  public String getHitPolicy() {
+    return hitPolicy;
+  }
+
+  public int getColumnCount() {
+    return columnCount;
+  }
+
+  public int getRowCount() {
+    return rowCount;
+  }
+
+  public double getAverageRunTime() {
+    return averageRunTime;
+  }
+
+  @Override
+  public String toString() {
+    return "ParserStatistic{"
+        + "hitPolicy='"
+        + hitPolicy
+        + '\''
+        + ", columnCount="
+        + columnCount
+        + ", rowCount="
+        + rowCount
+        + ", averageRunTime="
+        + averageRunTime
+        + '}';
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/statistic/PerformanceTestConfiguration.java b/dmn-generator/src/main/java/de/uniko/bks/statistic/PerformanceTestConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..83faa0be8ee51a0ef640be7151167e13ee10de20
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/statistic/PerformanceTestConfiguration.java
@@ -0,0 +1,46 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.statistic;
+
+/** Class containing the default configuration for performance tests */
+public class PerformanceTestConfiguration {
+  /** Amount (square root) of different data points (files) created */
+  private static final int NUMBER_OF_DATA_POINTS = 10;
+  /** Number of runs for each file to calculate the average run-time */
+  private static final int NUMBER_OF_TESTS = 3;
+  /** Whether or not the test files should be deleted after the statistics are generated */
+  private static final boolean DELETE_TEST_FILES = true;
+  /** Difference in rows in each test dmn file */
+  private static final int ROW_NUMBER_STEPS = 50;
+  /** Number of columns the generator starts with */
+  private static final int INITIAL_COLUMN_COUNT = 1;
+  /** Number of rows the generator starts with */
+  private static final int INITIAL_ROW_COUNT = 1;
+
+  public static int getNumberOfDataPoints() {
+    return NUMBER_OF_DATA_POINTS;
+  }
+
+  public static int getNumberOfTests() {
+    return NUMBER_OF_TESTS;
+  }
+
+  public static boolean isDeleteTestFiles() {
+    return DELETE_TEST_FILES;
+  }
+
+  public static int getRowNumberSteps() {
+    return ROW_NUMBER_STEPS;
+  }
+
+  public static int getInitialColumnCount() {
+    return INITIAL_COLUMN_COUNT;
+  }
+
+  public static int getInitialRowCount() {
+    return INITIAL_ROW_COUNT;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/statistic/PerformanceTester.java b/dmn-generator/src/main/java/de/uniko/bks/statistic/PerformanceTester.java
new file mode 100644
index 0000000000000000000000000000000000000000..191776d9689c66e6eb212d8e7b7c802d22ce0643
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/statistic/PerformanceTester.java
@@ -0,0 +1,221 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.statistic;
+
+import de.uniko.bks.cli.CliArgument;
+import de.uniko.bks.generator.DmnGenerator;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import javax.xml.bind.JAXBException;
+
+/** Class which processes automatic performance tests of the converter */
+public class PerformanceTester {
+
+  private static CliArgument cliArgument;
+
+  /**
+   * Function which calculates the average run-time of the conversion for one file
+   *
+   * @param runTimeList List of run-times for one test run
+   * @return The average run-time for the conversion of one file in milliseconds
+   */
+  private static double calculateAverageRunTime(ArrayList<Long> runTimeList) {
+    double totalRunTime = 0;
+    // Add upt the run-time from each run
+    for (Long runTime : runTimeList) {
+      totalRunTime += runTime;
+    }
+    // Calculate the average of the runtime
+    return (totalRunTime / cliArgument.getNumberOfTestRuns());
+  }
+
+  /**
+   * Function which runs the performance tests
+   *
+   * @param dmnFileList List of DMN files to process
+   * @return The average run-time of a conversion of one file
+   * @throws IOException Signals that an I/O exception of some sort has occurred
+   */
+  private static ArrayList<ArrayList<ParserStatistic>> runPerformanceTests(
+      ArrayList<DmnFile> dmnFileList) throws IOException {
+    ArrayList<ArrayList<ParserStatistic>> parserStatisticList = new ArrayList<>();
+
+    ArrayList<ParserStatistic> statistics = new ArrayList<>();
+    ArrayList<ParserStatistic> verifierStatistics = new ArrayList<>();
+    int size = dmnFileList.size() * cliArgument.getNumberOfTestRuns();
+    int j = 1;
+    for (DmnFile dmnFile : dmnFileList) {
+      ArrayList<Long> runTimeList = new ArrayList<>();
+      ArrayList<Long> verificationsFound = new ArrayList<>();
+      for (int i = 0; i < cliArgument.getNumberOfTestRuns(); i++) {
+        TestDMN testDMN = new TestDMN();
+        // Add the run-time of the current execution to the list of run-times for the file
+        testDMN.testDmn(dmnFile.getPath().toString());
+        verificationsFound.add(
+            testDMN
+                .getVerifcation()
+                .getVerifierResults()
+                .stream()
+                .map(verifierResult -> verifierResult.getVerifications().size())
+                .mapToLong(Long::valueOf)
+                .sum());
+        runTimeList.add(testDMN.getExecTime());
+        System.out.println(
+            "DMN " + j + " von " + size + " verified in " + testDMN.getExecTime() + "ms");
+        j++;
+      }
+      statistics.add(
+          new ParserStatistic(
+              dmnFile.getHitPolicy(),
+              dmnFile.getColumnCount(),
+              dmnFile.getRowCount(),
+              // Calculate the average run-time for the current file
+              calculateAverageRunTime(runTimeList)));
+      verifierStatistics.add(
+          new ParserStatistic(
+              "Count verifications found",
+              dmnFile.getColumnCount(),
+              dmnFile.getRowCount(),
+              // Calculate the average run-time for the current file
+              calculateAverageRunTime(verificationsFound)));
+    }
+    parserStatisticList.add(statistics);
+    parserStatisticList.add(verifierStatistics);
+    return parserStatisticList;
+  }
+
+  private static String toTikz(ArrayList<ParserStatistic> parserStatisticList) {
+    String newline = System.getProperty("line.separator");
+    StringBuilder tikzCode = new StringBuilder();
+    tikzCode.append("\\begin{figure}[h!]").append(newline);
+    tikzCode.append(" \\centering").append(newline);
+    tikzCode.append(" \\begin{tikzpicture}").append(newline);
+    tikzCode
+        .append("     \\begin{axis}")
+        .append(
+            "[xlabel=Number of columns, ylabel=Number of rows, zlabel=Run-time in milliseconds, xlabel style={sloped like x axis}, ylabel style={sloped}, view/az=45, zmin=0, grid=major]")
+        .append(newline);
+    tikzCode.append("         \\addplot3[surf, shader=faceted]").append(newline);
+    tikzCode.append("         coordinates {").append(newline);
+
+    // Add the coordinates (x=columnCount, y=rowCount, z=averageRunTime)
+    int i = 1;
+    for (ParserStatistic parserStatistic : parserStatisticList) {
+      // Create a matrix NUMBER_OF_DATA_POINTS X NUMBER_OF_DATA_POINTS
+      if (i == 1) {
+        tikzCode.append("         ");
+      }
+      tikzCode.append("(");
+      tikzCode.append(parserStatistic.getColumnCount()).append(", ");
+      tikzCode.append(parserStatistic.getRowCount()).append(", ");
+      tikzCode.append(parserStatistic.getAverageRunTime()).append(") ");
+
+      if (i % cliArgument.getNumberOfDataPoints() == 0 && i < parserStatisticList.size()) {
+        tikzCode.append(newline).append(newline).append("         ");
+      }
+      i++;
+    }
+
+    tikzCode.append(newline).append("       };").append(newline);
+    tikzCode.append("  \\end{axis}").append(newline);
+    tikzCode.append(" \\end{tikzpicture}").append(newline);
+    tikzCode
+        .append("\\caption{Run-time statistics for the ")
+        .append(parserStatisticList.get(0).getHitPolicy())
+        .append(" hit policy} ")
+        .append(newline);
+    tikzCode
+        .append("\\label{fig:statistic-")
+        .append(parserStatisticList.get(0).getHitPolicy().toLowerCase().replace(" ", "-"))
+        .append("}")
+        .append(newline);
+    tikzCode.append("\\end{figure}").append(newline);
+
+    return tikzCode.toString();
+  }
+
+  /**
+   * Function which generates the DMN files analyzed for performance
+   *
+   * @param hitPolicy Hit policy for the DMN table
+   * @return List of DMN files which should be tested
+   * @throws JAXBException Root exception for all JAXB exceptions
+   * @throws IOException Signals that an I/O exception of some sort has occurred
+   */
+  private static ArrayList<DmnFile> generateTestFiles(String hitPolicy, int rowNumberSteps)
+      throws JAXBException, IOException {
+    ArrayList<DmnFile> dmnFileList = new ArrayList<>();
+    // Create the given amount of files
+    for (int i = 1; i <= cliArgument.getNumberOfDataPoints(); i++) {
+      // Create the file
+      for (int j = 1; j <= cliArgument.getNumberOfDataPoints(); j++) {
+        Path filePath =
+            (DmnGenerator.generateDmnFile(
+                i + cliArgument.getInitialColumnCount(),
+                (rowNumberSteps * j) + cliArgument.getInitialRowCount(),
+                hitPolicy,
+                cliArgument.getOutputEntryList()));
+
+        // Add the file to the list of generated files
+        dmnFileList.add(
+            new DmnFile(
+                hitPolicy,
+                filePath,
+                i + cliArgument.getInitialColumnCount(),
+                (cliArgument.getRowSteps() * j) + cliArgument.getInitialRowCount()));
+      }
+    }
+    return dmnFileList;
+  }
+
+  /**
+   * Function which deletes a list of DMN files
+   *
+   * @param dmnFileList List of DMN files which should be deleted
+   * @throws IOException Signals that an I/O exception of some sort has occurred
+   */
+  private static void deleteTestFiles(ArrayList<DmnFile> dmnFileList) throws IOException {
+    for (DmnFile dmnFile : dmnFileList) {
+      Files.deleteIfExists(dmnFile.getPath());
+    }
+    // Add an information to the cli
+    System.out.println("Deleted " + dmnFileList.size() + " files successfully");
+  }
+
+  public static void main(String argv[]) throws JAXBException, IOException {
+    cliArgument = new CliArgument(argv);
+    // Measure the start time
+    RunTimePrinter runTimePrinter = new RunTimePrinter(System.currentTimeMillis());
+
+    ArrayList<ArrayList<DmnFile>> dmnFileLists = new ArrayList<>();
+    ArrayList<String> tikzPictureList = new ArrayList<>();
+    // Generate the DMN files
+    dmnFileLists.add(generateTestFiles("COLLECT", cliArgument.getRowSteps()));
+    // Run the performance tests
+    for (ArrayList<DmnFile> dmnFileList : dmnFileLists) {
+      ArrayList<ArrayList<ParserStatistic>> parserStatisticList = runPerformanceTests(dmnFileList);
+      // Generate tikz code
+      for (ArrayList<ParserStatistic> set : parserStatisticList) {
+        tikzPictureList.add(toTikz(set));
+      }
+
+      // Delete the generated test files if needed
+      if (PerformanceTestConfiguration.isDeleteTestFiles()) {
+        deleteTestFiles(dmnFileList);
+      }
+    }
+
+    // Print the tikz code of the statistics
+    tikzPictureList.forEach(System.out::println);
+
+    // Measure the end time
+    runTimePrinter.setEndTime(System.currentTimeMillis());
+    // Print the total execution time
+    System.out.println(runTimePrinter.toString());
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/statistic/RunTimePrinter.java b/dmn-generator/src/main/java/de/uniko/bks/statistic/RunTimePrinter.java
new file mode 100644
index 0000000000000000000000000000000000000000..dfd97a214e0021a54edf287ec8485f0e577fb2f1
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/statistic/RunTimePrinter.java
@@ -0,0 +1,34 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.statistic;
+
+import java.util.concurrent.TimeUnit;
+
+/** Class which handles the printing/formatting of the statistic run-time */
+public class RunTimePrinter {
+  private long startTime;
+  private long endTime;
+  private static final String PRINTER_TEXT =
+      "\u001B[32mThe generation of statistics took %d minutes and %d seconds\u001B[0m";
+
+  RunTimePrinter(long startTime) {
+    this.startTime = startTime;
+  }
+
+  void setEndTime(long endTime) {
+    this.endTime = endTime;
+  }
+
+  @Override
+  public String toString() {
+    long executionTime = this.endTime - this.startTime;
+    return String.format(
+        PRINTER_TEXT,
+        TimeUnit.MILLISECONDS.toMinutes(executionTime),
+        TimeUnit.MILLISECONDS.toSeconds(executionTime)
+            - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(executionTime)));
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/statistic/TestDMN.java b/dmn-generator/src/main/java/de/uniko/bks/statistic/TestDMN.java
new file mode 100644
index 0000000000000000000000000000000000000000..a1031c5ddb2f6b2efbb5d2ee4cb6df12c0446e19
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/statistic/TestDMN.java
@@ -0,0 +1,44 @@
+package de.uniko.bks.statistic;
+
+import de.unikoblenz.fgbks.dmn.core.models.VerifierCollectionResult;
+import de.unikoblenz.fgbks.dmn.core.models.VerifierType;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.util.List;
+import org.camunda.bpm.dmn.engine.DmnDecision;
+import org.camunda.bpm.dmn.engine.DmnEngineConfiguration;
+
+public class TestDMN {
+
+  // Multimap<String, String> outputMap = MultimapBuilder.hashKeys().hashSetValues().build();
+  private List<DmnDecision> dmnDecisions = null;
+  private VerifierCollectionResult verifcation;
+  private long execTime = 0;
+
+  public List<DmnDecision> testDmn(String filePath) throws FileNotFoundException {
+    InputStream inputStream = new FileInputStream(filePath);
+    this.dmnDecisions =
+        DmnEngineConfiguration.createDefaultDmnEngineConfiguration()
+            .buildEngine()
+            .parseDecisions(inputStream);
+
+    execTime = System.currentTimeMillis();
+    checkAllTables();
+    execTime = System.currentTimeMillis() - execTime;
+    // checkTest();
+    return this.dmnDecisions;
+  }
+
+  public VerifierCollectionResult getVerifcation() {
+    return verifcation;
+  }
+
+  public long getExecTime() {
+    return execTime;
+  }
+
+  private void checkAllTables() {
+    verifcation = VerifierType.getAllResults(this.dmnDecisions);
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/statistic/dmnInt.java b/dmn-generator/src/main/java/de/uniko/bks/statistic/dmnInt.java
new file mode 100644
index 0000000000000000000000000000000000000000..3a97131c0cc0306dfc5a4afe3e99a0b4249ee1d3
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/statistic/dmnInt.java
@@ -0,0 +1,463 @@
+package de.uniko.bks.statistic;
+
+public class dmnInt {
+  private boolean isRange = false;
+  private boolean isLower = false;
+  private boolean isGreater = false;
+  private boolean isEqual = false;
+  private boolean isInt = false;
+  private boolean isLong = false;
+  private boolean isDouble = false;
+  private int lowerBoundInt;
+  private int upperBoundInt;
+  private int numberInt;
+  private double numberDouble;
+  private double lowerBoundDouble;
+  private double upperBoundDouble;
+  private long numberLong;
+  private long lowerBoundLong;
+  private long upperBoundLong;
+  private String ruleName = "";
+  private String originalText = "";
+  private boolean isDoesntMatter = false;
+  final char eq = "=".charAt(0);
+  final char lt = "<".charAt(0);
+  final char gt = ">".charAt(0);
+
+  void setRuleName(String ruleName) {
+    this.ruleName = ruleName;
+  }
+
+  public String getRuleName() {
+    return ruleName;
+  }
+
+  public boolean isRange() {
+    return isRange;
+  }
+
+  public boolean isLower() {
+    return isLower;
+  }
+
+  public boolean isGreater() {
+    return isGreater;
+  }
+
+  public boolean isEqual() {
+    return isEqual;
+  }
+
+  public int getLowerBoundInt() {
+    return lowerBoundInt;
+  }
+
+  public int getUpperBoundInt() {
+    return upperBoundInt;
+  }
+
+  public int getNumberInt() {
+    return numberInt;
+  }
+
+  public double getNumberDouble() {
+    return numberDouble;
+  }
+
+  public double getLowerBoundDouble() {
+    return lowerBoundDouble;
+  }
+
+  public double getUpperBoundDouble() {
+    return upperBoundDouble;
+  }
+
+  public long getNumberLong() {
+    return numberLong;
+  }
+
+  public long getLowerBoundLong() {
+    return lowerBoundLong;
+  }
+
+  public long getUpperBoundLong() {
+    return upperBoundLong;
+  }
+
+  public boolean isInt() {
+    return isInt;
+  }
+
+  public boolean isLong() {
+    return isLong;
+  }
+
+  public boolean isDouble() {
+    return isDouble;
+  }
+
+  public dmnInt(int number) {
+    this.isInt = true;
+    this.numberInt = number;
+    this.lowerBoundInt = number;
+    this.upperBoundInt = numberInt;
+    this.isEqual = true;
+  }
+
+  public dmnInt(double number) {
+    this.numberDouble = number;
+    this.lowerBoundDouble = number;
+    this.upperBoundDouble = number;
+    this.isDouble = true;
+  }
+
+  public dmnInt(long number) {
+    this.numberLong = number;
+    this.lowerBoundLong = number;
+    this.upperBoundLong = number;
+  }
+
+  public dmnInt(int lowerBoundInt, int upperBoundInt) {
+    this.upperBoundInt = upperBoundInt;
+    this.lowerBoundInt = lowerBoundInt;
+    this.isRange = true;
+    this.isInt = true;
+  }
+
+  public dmnInt(double lowerBoundDouble, double upperBoundDouble) {
+    this.upperBoundDouble = upperBoundDouble;
+    this.lowerBoundDouble = lowerBoundDouble;
+    this.isRange = true;
+    this.isDouble = true;
+  }
+
+  public dmnInt(long lowerBoundLong, long upperBoundLong) {
+    this.lowerBoundLong = lowerBoundLong;
+    this.upperBoundLong = upperBoundLong;
+    this.isRange = true;
+  }
+
+  public dmnInt(int number, boolean isLower, boolean isGreater, boolean isEqual) {
+    if (isLower && isGreater) {
+      System.out.println("ERROR: Number can't be lower and greater...");
+    }
+    this.isInt = true;
+    this.isEqual = isEqual;
+    this.isGreater = isGreater;
+    this.isLower = isLower;
+    this.numberInt = number;
+  }
+
+  public dmnInt(boolean itDoesntMatter) {
+    this.isDoesntMatter = true;
+  }
+
+  public dmnInt(String term, String type) {
+    String modTerm = term;
+
+    char c = term.charAt(0);
+
+    if (lt == c) {
+      this.isLower = true;
+      modTerm = modTerm.replace("<", "");
+    } else if (gt == c) {
+      this.isGreater = true;
+      modTerm = modTerm.replace(">", "");
+    }
+    c = term.charAt(1);
+    if (eq == c) {
+      this.isEqual = true;
+      modTerm = modTerm.replace("=", "");
+    }
+
+    modTerm = modTerm.replace(" ", "");
+
+    switch (type) {
+      case "integer":
+        this.numberInt = Integer.parseInt(modTerm);
+        this.isInt = true;
+      case "double":
+        this.numberDouble = Double.parseDouble(modTerm);
+        this.isDouble = true;
+      case "long":
+        this.numberLong = Long.parseLong(modTerm);
+        this.isLong = true;
+    }
+    if (!this.isLower && !this.isGreater && !this.isEqual) {
+      this.isEqual = true;
+    }
+  }
+
+  public dmnInt(double number, boolean isLower, boolean isGreater, boolean isEqual) {
+    if (isLower && isGreater) {
+      System.out.println("ERROR: Number can't be lower and greater...");
+    }
+    this.isDouble = true;
+    this.isEqual = isEqual;
+    this.isGreater = isGreater;
+    this.isLower = isLower;
+    this.numberDouble = number;
+  }
+
+  public dmnInt(long number, boolean isLower, boolean isGreater, boolean isEqual) {
+    if (isLower && isGreater) {
+      System.out.println("ERROR: Number can't be lower and greater...");
+    }
+
+    this.isEqual = isEqual;
+    this.isGreater = isGreater;
+    this.isLower = isLower;
+    this.numberLong = number;
+  }
+
+  public boolean compare(dmnInt sndNum) {
+    if (this.isDoesntMatter || sndNum.isDoesntMatter()) {
+      return true;
+    }
+    if (this.isRange) {
+      return range(this, sndNum);
+    }
+    if (sndNum.isRange) {
+      return range(sndNum, this);
+    }
+    return bothNumbers(this, sndNum);
+  }
+
+  public boolean bothNumbers(dmnInt x, dmnInt y) {
+    if (x.isLower) {
+      if (y.isLower) {
+        if (y.isInt && x.isInt) {
+          if (x.numberInt < y.numberInt || y.numberInt < x.numberInt) {
+            return true;
+          }
+        } else if (y.isDouble && x.isDouble) {
+          if (x.numberDouble < y.numberDouble || y.numberDouble < x.numberDouble) {
+            return true;
+          }
+        } else if (y.isLong && x.isLong) {
+          if (x.numberLong < y.numberLong || y.numberLong < x.numberLong) {
+            return true;
+          }
+        }
+      }
+      if (y.isEqual) {
+        if (y.isInt && x.isInt) {
+          if (x.numberInt > y.numberInt) {
+            return true;
+          }
+        } else if (y.isDouble && x.isDouble) {
+          if (x.numberDouble > y.numberDouble) {
+            return true;
+          }
+        } else if (y.isLong && x.isLong) {
+          if (x.numberLong > y.numberLong) {
+            return true;
+          }
+        }
+      }
+      if (y.isGreater) {
+        if (y.isInt && x.isInt) {
+          if ((x.numberInt != y.numberInt)
+              && (y.numberInt < x.numberInt || x.numberInt > y.numberInt)) {
+            return true;
+          }
+        } else if (y.isDouble && x.isDouble) {
+          if ((x.numberDouble != y.numberDouble)
+              && (y.numberDouble < x.numberDouble || x.numberDouble > y.numberDouble)) {
+            return true;
+          }
+        } else if (y.isLong && x.isLong) {
+          if ((x.numberLong != y.numberLong)
+              && (y.numberLong < x.numberLong || x.numberLong > y.numberLong)) {
+            return true;
+          }
+        }
+      }
+    }
+    if (x.isEqual) {
+      if (y.isLower) {
+        if (y.isInt && x.isInt) {
+          if (x.numberInt < y.numberInt) {
+            return true;
+          }
+        } else if (y.isDouble && x.isDouble) {
+          if (x.numberDouble < y.numberDouble) {
+            return true;
+          }
+        } else if (y.isLong && x.isLong) {
+          if (x.numberLong < y.numberLong) {
+            return true;
+          }
+        }
+      }
+      if (y.isEqual) {
+        if (y.isInt && x.isInt) {
+          if (x.numberInt == y.numberInt) {
+            return true;
+          }
+        } else if (y.isDouble && x.isDouble) {
+          if (x.numberDouble == y.numberDouble) {
+            return true;
+          }
+        } else if (y.isLong && x.isLong) {
+          if (x.numberLong == y.numberLong) {
+            return true;
+          }
+        }
+      }
+      if (y.isGreater) {
+        if (y.isInt && x.isInt) {
+          if (x.numberInt > y.numberInt) {
+            return true;
+          }
+        } else if (y.isDouble && x.isDouble) {
+          if (x.numberDouble > y.numberDouble) {
+            return true;
+          }
+        } else if (y.isLong && x.isLong) {
+          if (x.numberLong > y.numberLong) {
+            return true;
+          }
+        }
+      }
+    }
+    if (x.isGreater) {
+      if (y.isLower) {
+        if (y.isInt && x.isInt) {
+          if ((x.numberInt != y.numberInt)
+              && (y.numberInt > x.numberInt || x.numberInt < y.numberInt)) {
+            return true;
+          }
+        } else if (y.isDouble && x.isDouble) {
+          if ((x.numberDouble != y.numberDouble)
+              && (y.numberDouble > x.numberDouble || x.numberDouble < y.numberDouble)) {
+            return true;
+          }
+        } else if (y.isLong && x.isLong) {
+          if ((x.numberLong != y.numberLong)
+              && (y.numberLong > x.numberLong || x.numberLong < y.numberLong)) {
+            return true;
+          }
+        }
+      }
+    }
+    return false;
+  }
+
+  public boolean rangeTest(int number, int lower, int upper) {
+    if ((number > lower && number < upper) || (number == lower) || (number == upper)) {
+      return true;
+    }
+    return false;
+  }
+
+  public boolean rangeTest(double number, double lower, double upper) {
+    if (((number > lower && number < upper) || (number == lower) || (number == upper))) {
+      return true;
+    }
+    return false;
+  }
+
+  public boolean rangeTest(long number, long lower, long upper) {
+    if ((number > lower && number < upper) || (number == lower) || (number == upper)) {
+      return true;
+    }
+    return false;
+  }
+
+  public boolean range(dmnInt x, dmnInt y) {
+    if (x.isRange) {
+      if (y.isRange) {
+        if (y.isInt && x.isInt) {
+          // Case if both is int range
+          if (rangeTest(x.lowerBoundInt, y.lowerBoundInt, y.upperBoundInt)
+              || rangeTest(x.upperBoundInt, y.lowerBoundInt, y.upperBoundInt)
+              || rangeTest(y.lowerBoundInt, x.lowerBoundInt, x.upperBoundInt)
+              || rangeTest(y.upperBoundInt, x.lowerBoundInt, x.upperBoundInt)) {
+            return true;
+          }
+          return false;
+
+        } else if (y.isDouble && x.isDouble) {
+          if (rangeTest(x.lowerBoundDouble, y.lowerBoundDouble, y.upperBoundDouble)
+              || rangeTest(x.upperBoundDouble, y.lowerBoundDouble, y.upperBoundDouble)
+              || rangeTest(y.lowerBoundDouble, x.lowerBoundDouble, x.upperBoundDouble)
+              || rangeTest(y.upperBoundDouble, x.lowerBoundDouble, x.upperBoundDouble)) {
+            return true;
+          }
+          return false;
+        } else if (y.isLong && x.isLong) {
+          if (rangeTest(x.lowerBoundLong, y.lowerBoundLong, y.upperBoundLong)
+              || rangeTest(x.upperBoundLong, y.lowerBoundLong, y.upperBoundLong)
+              || rangeTest(y.lowerBoundLong, x.lowerBoundLong, x.upperBoundLong)
+              || rangeTest(y.upperBoundLong, x.lowerBoundLong, x.upperBoundLong)) {
+            return true;
+          }
+          return false;
+        }
+      } else {
+        if (y.isInt && x.isInt) {
+          // Case if both is int range
+          if (y.isEqual) {
+            if (rangeTest(y.numberInt, x.lowerBoundInt, x.upperBoundInt)) {
+              return true;
+            }
+          }
+          if (y.isLower) {
+            if (x.lowerBoundInt < y.numberInt) {
+              return true;
+            }
+            return false;
+          }
+          if (y.isGreater) {
+            if (x.upperBoundInt > y.numberInt) {
+              return true;
+            }
+            return false;
+          }
+        } else if (y.isDouble && x.isDouble) {
+          if (y.isEqual) {
+            if (rangeTest(y.numberDouble, x.lowerBoundDouble, x.upperBoundDouble)) {
+              return true;
+            }
+          }
+          if (y.isLower) {
+            if (x.lowerBoundDouble < y.numberDouble) {
+              return true;
+            }
+            return false;
+          }
+          if (y.isGreater) {
+            if (x.upperBoundDouble > y.numberDouble) {
+              return true;
+            }
+            return false;
+          }
+        } else if (y.isLong && x.isLong) {
+          if (y.isEqual) {
+            if (rangeTest(y.numberLong, x.lowerBoundLong, x.upperBoundLong)) {
+              return true;
+            }
+          }
+          if (y.isLower) {
+            if (x.lowerBoundLong < y.numberLong) {
+              return true;
+            }
+            return false;
+          }
+          if (y.isGreater) {
+            if (x.upperBoundLong > y.numberLong) {
+              return true;
+            }
+            return false;
+          }
+        }
+      }
+    }
+    return false;
+  }
+
+  public boolean isDoesntMatter() {
+    return isDoesntMatter;
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/util/StringSanitizer.java b/dmn-generator/src/main/java/de/uniko/bks/util/StringSanitizer.java
new file mode 100644
index 0000000000000000000000000000000000000000..0900bd733655b084e2c087bae02c2b4fd7874b15
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/util/StringSanitizer.java
@@ -0,0 +1,150 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.util;
+
+import de.uniko.bks.dom.dfl.rule.Comparator;
+import de.uniko.bks.dom.dfl.rule.RuleDelimiter;
+
+/** Class providing functions to sanitize strings */
+public class StringSanitizer {
+  /**
+   * Function which removes whitespaces from a given text
+   *
+   * @param text Text in which all whitespaces should be removed
+   * @return The sanitized text
+   */
+  private static String replaceWhitespace(String text) {
+    text = text.replace(Comparator.SMALLER.getValue() + " ", Comparator.SMALLER.getValue());
+    text =
+        text.replace(
+            Comparator.SMALLER_OR_EQUALS.getValue() + " ", Comparator.SMALLER_OR_EQUALS.getValue());
+    text =
+        text.replace(
+            Comparator.GREATER_OR_EQUALS.getValue() + " ", Comparator.GREATER_OR_EQUALS.getValue());
+    text = text.replace(Comparator.GREATER.getValue() + " ", Comparator.GREATER.getValue());
+
+    return text.replace(" ", RuleDelimiter.WHITESPACE.getValue());
+  }
+
+  /**
+   * Function which removes double quotes from a given text
+   *
+   * @param text Text in which all double quotes should be removed
+   * @return The sanitized text
+   */
+  private static String replaceQuotes(String text) {
+    return text.replace("\"", "");
+  }
+
+  /**
+   * Function which removes colons from a given text
+   *
+   * @param text Text in which all colons should be removed
+   * @return The sanitized text
+   */
+  private static String replaceColon(String text) {
+    return text.replace(":", "");
+  }
+
+  /**
+   * Function which removes dashes from a given text
+   *
+   * @param text Text in which all dashes should be removed
+   * @return The sanitized text
+   */
+  private static String replaceDash(String text) {
+    return text.replace(
+        "-", RuleDelimiter.WHITESPACE.getValue() + RuleDelimiter.WHITESPACE.getValue());
+  }
+
+  /**
+   * Function which sanitizes whitespaces
+   *
+   * @param text Text in which all whitespaces should be sanitized
+   * @return The sanitized text
+   */
+  public static String sanitize(String text) {
+    return sanitize(text, true, true, true, true);
+  }
+
+  /**
+   * Function which sanitizes whitespaces
+   *
+   * @param text Text in which all whitespaces should be sanitized
+   * @param replaceWhitespace Whether or not whitespaces should be sanitized
+   * @return The sanitized text
+   */
+  public static String sanitize(String text, boolean replaceWhitespace) {
+    return sanitize(text, replaceWhitespace, false, false, false);
+  }
+
+  /**
+   * Function which sanitizes whitespaces and double quotes
+   *
+   * @param text Text which should be sanitized
+   * @param replaceWhitespace Whether or not whitespaces should be sanitized
+   * @param replaceQuotes Whether or not double quotes should be sanitized
+   * @return The sanitized text
+   */
+  public static String sanitize(String text, boolean replaceWhitespace, boolean replaceQuotes) {
+    return sanitize(text, replaceWhitespace, replaceQuotes, false, false);
+  }
+
+  /**
+   * Function which sanitizes whitespaces, double quotes and colons
+   *
+   * @param text Text which should be sanitized
+   * @param replaceWhitespace Whether or not whitespaces should be sanitized
+   * @param replaceQuotes Whether or not double quotes should be sanitized
+   * @param replaceColon Whether or not colons should be sanitized
+   * @return The sanitized text
+   */
+  public static String sanitize(
+      String text, boolean replaceWhitespace, boolean replaceQuotes, boolean replaceColon) {
+    return sanitize(text, replaceWhitespace, replaceQuotes, replaceColon, false);
+  }
+
+  /**
+   * Function which sanitizes whitespaces, double quotes and colons
+   *
+   * @param text Text which should be sanitized
+   * @param replaceWhitespace Whether or not whitespaces should be sanitized
+   * @param replaceQuotes Whether or not double quotes should be sanitized
+   * @param replaceColon Whether or not colons should be sanitized
+   * @param replaceDash Whether or not dashes should be sanitized
+   * @return The sanitized text
+   */
+  public static String sanitize(
+      String text,
+      boolean replaceWhitespace,
+      boolean replaceQuotes,
+      boolean replaceColon,
+      boolean replaceDash) {
+    if (replaceWhitespace) {
+      text = replaceWhitespace(text);
+    }
+    if (replaceQuotes) {
+      text = replaceQuotes(text);
+    }
+    if (replaceColon) {
+      text = replaceColon(text);
+    }
+    if (replaceDash) {
+      text = replaceDash(text);
+    }
+    return text;
+  }
+
+  /**
+   * Function removes whitespaces after commas
+   *
+   * @param text Text in which all whitespaces after commas should be removed
+   * @return The text without whitespaces after commas
+   */
+  public static String removeWhitespacesAfterComma(String text) {
+    return text.replaceAll(",\\s+", ",");
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/xml/FileHandler.java b/dmn-generator/src/main/java/de/uniko/bks/xml/FileHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..e0bf0b654453bfaf4b58eb89d1e4ef6c53d67a34
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/xml/FileHandler.java
@@ -0,0 +1,89 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.xml;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.stream.Collectors;
+
+/** Class which provides basic functionalities for handling files */
+public class FileHandler {
+  private static final String FILE_EXTENSION = ".xml";
+
+  /**
+   * Function which reads a file into a variable
+   *
+   * @param fileName Name of the file which should be read
+   * @return The content of the given file
+   */
+  public static String read(String fileName) {
+    // Get the class loader to load the resource
+    ClassLoader classLoader = FileHandler.class.getClassLoader();
+    InputStream inputStream = classLoader.getResourceAsStream(fileName);
+
+    // Convert the stream into a String
+    return new BufferedReader(new InputStreamReader(inputStream))
+        .lines()
+        .collect(Collectors.joining("\n"));
+  }
+
+  /**
+   * Function which reads a file into a variable
+   *
+   * @param filePath Complete path of the file which should be read
+   * @return The content of the given file
+   * @throws IOException Signals that an I/O exception of some sort has occurred
+   */
+  public static String read(Path filePath) throws IOException {
+    return new String(Files.readAllBytes(filePath), StandardCharsets.UTF_8);
+  }
+
+  /**
+   * Function which generates a name for the DMN file
+   *
+   * @param identifier Identifier suffix for all ids in the DMN decision
+   * @param columnCount Number of columns in the DMN table
+   * @param rowCount Number of rows in the DMN table
+   * @param hitPolicy Hit policy for the DMN table
+   * @return The name of the generated DMN file
+   */
+  private static String generateFileName(
+      String identifier, int columnCount, int rowCount, String hitPolicy) {
+    return "generated_dmn_c"
+        + columnCount
+        + "_r"
+        + rowCount
+        + "_h"
+        + hitPolicy.replace(" ", "_")
+        + "_"
+        + identifier;
+  }
+
+  /**
+   * Function which writes a given content into a new file
+   *
+   * @param identifier Identifier suffix for all ids in the DMN decision
+   * @param columnCount Number of columns in the DMN table
+   * @param rowCount Number of rows in the DMN table
+   * @param content The content which is written into the new file
+   * @param hitPolicy Hit policy for the DMN table
+   * @return The path of the new file
+   * @throws IOException Signals that an I/O exception of some sort has occurred
+   */
+  public static Path write(
+      String identifier, int columnCount, int rowCount, String hitPolicy, String content)
+      throws IOException {
+    // Write the file to the temporary directory of the os
+    File file =
+        File.createTempFile(
+            generateFileName(identifier, columnCount, rowCount, hitPolicy), FILE_EXTENSION);
+
+    // Fill the generated file with content
+    return Files.write(file.toPath(), content.getBytes());
+  }
+}
diff --git a/dmn-generator/src/main/java/de/uniko/bks/xml/XmlMarshaller.java b/dmn-generator/src/main/java/de/uniko/bks/xml/XmlMarshaller.java
new file mode 100644
index 0000000000000000000000000000000000000000..c42947f616375253a6eac496d43252175d1ede12
--- /dev/null
+++ b/dmn-generator/src/main/java/de/uniko/bks/xml/XmlMarshaller.java
@@ -0,0 +1,34 @@
+/*
+ * Developed by Hans-Henning Ramberger as part of a master thesis.
+ * Copyright (c) 2018.
+ */
+
+package de.uniko.bks.xml;
+
+import de.uniko.bks.dom.dmn.Decision;
+import java.io.StringWriter;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+
+/** Class marshalling a given Java Decision into XML */
+public class XmlMarshaller {
+  public static String marshalDmnTable(Decision decision) throws JAXBException {
+    JAXBContext jaxbContext = JAXBContext.newInstance(Decision.class);
+    Marshaller marshaller = jaxbContext.createMarshaller();
+
+    // Format the resulting XML
+    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+    // Tell the marshaller to only write the XML fragment without the header
+    marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
+    // Set the correct encoding
+    marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
+
+    // Create a variable to store the marshalling result
+    StringWriter stringWriter = new StringWriter();
+    // Marshal the decision into a variable
+    marshaller.marshal(decision, stringWriter);
+
+    return stringWriter.toString();
+  }
+}
diff --git a/dmn-generator/src/main/resources/EmptyDmn.xml b/dmn-generator/src/main/resources/EmptyDmn.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a2d65c7749cda2cc0545c6f33539ec00daf701e6
--- /dev/null
+++ b/dmn-generator/src/main/resources/EmptyDmn.xml
@@ -0,0 +1,7 @@
+<?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_1epahzp" name="DRD" namespace="http://camunda.org/schema/1.0/dmn">
+    <extensionElements>
+        <biodi:bounds x="150" y="150" width="180" height="80" />
+    </extensionElements>
+    <!--replace-me-->
+</definitions>
\ No newline at end of file
diff --git a/dmn-generator/src/test/java/PerformanceTest.java b/dmn-generator/src/test/java/PerformanceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9f50961f419e3e4cac2f7adb324e3ee2034e5a0e
--- /dev/null
+++ b/dmn-generator/src/test/java/PerformanceTest.java
@@ -0,0 +1,17 @@
+import de.uniko.bks.statistic.PerformanceTester;
+import java.io.IOException;
+import javax.xml.bind.JAXBException;
+import org.junit.jupiter.api.Test;
+
+public class PerformanceTest {
+  @Test
+  public void perfTest() {
+    try {
+      PerformanceTester.main(new String[] {""});
+    } catch (JAXBException e) {
+      e.printStackTrace();
+    } catch (IOException e) {
+      e.printStackTrace();
+    }
+  }
+}
diff --git a/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/DmnService.java b/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/DmnService.java
index cfca8a3e1b0311487335761090cdb6eb4c6b8fc5..511694da1f7a49b32b4edad3f5b1e84e4b01c29b 100644
--- a/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/DmnService.java
+++ b/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/DmnService.java
@@ -43,7 +43,7 @@ public class DmnService {
   }
 
   public VerifierResult getVerifierFromType(VerifierType verifierType) {
-    return verifierType.getResult(dmnDecisions, null).orElse(null);
+    return verifierType.getResult(dmnDecisions, null, null).orElse(null);
   }
 
   public VerifierCollectionResult getAllVerifier() {
diff --git a/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/models/VerifierCollectionResult.java b/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/models/VerifierCollectionResult.java
index 07492e90a5c12164bedb1e9962bfc38379d3a295..f1737831619fc4e6cb2fd8ac5d4ace4629b31a99 100644
--- a/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/models/VerifierCollectionResult.java
+++ b/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/models/VerifierCollectionResult.java
@@ -5,6 +5,7 @@ import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.List;
 import java.util.Objects;
+import java.util.concurrent.CopyOnWriteArrayList;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 
@@ -15,7 +16,7 @@ public class VerifierCollectionResult {
   private List<VerifierResult> verifierResults;
 
   private VerifierCollectionResult() {
-    verifierResults = new ArrayList<>();
+    verifierResults = new CopyOnWriteArrayList<>();
   }
 
   public List<VerifierResult> getVerifierResults() {
@@ -28,7 +29,7 @@ public class VerifierCollectionResult {
 
   public class Builder extends DefaultBuilder<VerifierCollectionResult> {
 
-    public VerifierCollectionResult.Builder addVerification(VerifierResult verificationResult) {
+    public VerifierCollectionResult.Builder addVerifierResult(VerifierResult verificationResult) {
       value.verifierResults.add(Objects.requireNonNull(verificationResult));
       return this;
     }
diff --git a/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/models/VerifierType.java b/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/models/VerifierType.java
index 56cdd1442031c1c15887a939c5bf3cd03d48a6e7..9e2d47b1ce709d223f46484d4fe4c81033593ca3 100644
--- a/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/models/VerifierType.java
+++ b/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/models/VerifierType.java
@@ -6,37 +6,54 @@ import de.unikoblenz.fgbks.dmn.core.verifier.helper.RuleMap;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
+import java.util.concurrent.ConcurrentLinkedQueue;
 import org.camunda.bpm.dmn.engine.DmnDecision;
 import org.slf4j.LoggerFactory;
 
 public enum VerifierType {
-  Identical("Checking for identical rules.", IdenticalRules.class),
-  Subsumption("Checking for rules, which subsume other rules.", SubsumptionRules.class),
-  Equivalent("Checking for synonyms in columns.", EquivalentRules.class),
-  Overlap("Checking for overlapping rules.", OverlappingRules.class),
-  Missing("Checking for missing rules.", MissingRules.class),
+  Identical("Checking for identical rules.", IdenticalRules.class, true),
+  Subsumption("Checking for rules, which subsume other rules.", SubsumptionRules.class, true),
+  Equivalent("Checking for synonyms in columns.", EquivalentRules.class, true),
+  Overlap("Checking for overlapping rules.", OverlappingRules.class, true),
+  Missing("Checking for missing rules.", MissingRules.class, true),
   PartialReduction(
-      "Checking for partial reduction of rules (combination).", PartialReductionRules.class);
+      "Checking for partial reduction of rules (combination).", PartialReductionRules.class, true),
+  Interdeterminism(
+      "Identical, Overlapping or Subsumption with different conclusions.",
+      InterdeterminismRules.class,
+      false);
 
   private final Class<? extends AbstractVerifier> verifierClass;
   private String description;
+  private boolean autoExecutable;
 
-  VerifierType(String description, Class<? extends AbstractVerifier> verifierClass) {
+  VerifierType(
+      String description, Class<? extends AbstractVerifier> verifierClass, boolean autoExecutable) {
     this.description = description;
     this.verifierClass = verifierClass;
+    this.autoExecutable = autoExecutable;
   }
 
   public String getDescription() {
     return description;
   }
 
-  public Optional<VerifierResult> getResult(List<DmnDecision> dmnDecisionList, RuleMap ruleMap) {
+  private boolean isAutoExecutable() {
+    return autoExecutable;
+  }
+
+  public Optional<VerifierResult> getResult(
+      List<DmnDecision> dmnDecisionList,
+      RuleMap ruleMap,
+      ConcurrentLinkedQueue<VerificationResult> interdeterminismRules) {
     if (ruleMap == null) {
       ruleMap = RuleMap.createMapFromDmn(dmnDecisionList);
     }
     try {
       return Optional.of(
-          verifierClass.newInstance().findValidationErrors(dmnDecisionList, ruleMap));
+          verifierClass
+              .newInstance()
+              .findValidationErrors(dmnDecisionList, ruleMap, interdeterminismRules));
     } catch (Exception ex) {
       LoggerFactory.getLogger(VerifierType.class).warn(ex.getMessage());
       ex.printStackTrace();
@@ -46,14 +63,18 @@ public enum VerifierType {
 
   public static VerifierCollectionResult getAllResults(List<DmnDecision> dmnDecisionList) {
     RuleMap ruleMap = RuleMap.createMapFromDmn(dmnDecisionList);
+    ConcurrentLinkedQueue<VerificationResult> interdeterminismRules = new ConcurrentLinkedQueue<>();
     Builder builder = VerifierCollectionResult.getBuilder();
     Arrays.asList(values())
         .parallelStream()
+        .filter(VerifierType::isAutoExecutable)
         .forEach(
             verifierType ->
                 verifierType
-                    .getResult(dmnDecisionList, ruleMap)
-                    .ifPresent(builder::addVerification));
+                    .getResult(dmnDecisionList, ruleMap, interdeterminismRules)
+                    .ifPresent(builder::addVerifierResult));
+    Interdeterminism.getResult(dmnDecisionList, ruleMap, interdeterminismRules)
+        .ifPresent(builder::addVerifierResult);
     return builder.build();
   }
 }
diff --git a/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/AbstractVerifier.java b/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/AbstractVerifier.java
index 8e15bc88477306c95eddf6ce17e2c5729c2a4e6e..4fa153e6fe078b5891be4cb3d5d90fd6fb63c3d1 100644
--- a/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/AbstractVerifier.java
+++ b/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/AbstractVerifier.java
@@ -8,8 +8,10 @@ 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.LinkedList;
 import java.util.List;
 import java.util.Objects;
+import java.util.Queue;
 import java.util.logging.Logger;
 import org.camunda.bpm.dmn.engine.DmnDecision;
 
@@ -21,17 +23,24 @@ public abstract class AbstractVerifier {
   private VerifierResult.Builder verifierResultBuilder;
   protected List<DmnDecision> dmnDecisionList;
   protected RuleMap ruleMap;
+  protected Queue<VerificationResult> interdeterminismRules;
 
   protected AbstractVerifier(VerifierType verifierType) {
     this.verifierType = Objects.requireNonNull(verifierType);
   }
 
   public final VerifierResult findValidationErrors(
-      final List<DmnDecision> dmnDecisionList, final RuleMap ruleMap) {
-    LOGGER.info("Start verifyDecision " + this.getClass().getSimpleName());
+      final List<DmnDecision> dmnDecisionList,
+      final RuleMap ruleMap,
+      Queue<VerificationResult> interdeterminismRules) {
+    // LOGGER.info("Start verifyDecision " + this.getClass().getSimpleName());
     long start = System.currentTimeMillis();
     this.dmnDecisionList = new ArrayList<>(dmnDecisionList);
     this.ruleMap = ruleMap;
+    if (interdeterminismRules == null) {
+      interdeterminismRules = new LinkedList<>();
+    }
+    this.interdeterminismRules = interdeterminismRules;
     verifierResultBuilder = VerifierResult.getBuilder().withVerifierType(verifierType);
     beforeVerifyDecision();
     for (DmnDecision d : dmnDecisionList) {
@@ -39,12 +48,14 @@ public abstract class AbstractVerifier {
     }
     afterVerifyDecision();
     long fin = System.currentTimeMillis();
+    /*
     LOGGER.info(
         "Finish verifyDecision "
             + this.getClass().getSimpleName()
             + ". "
             + "Time: "
             + (fin - start));
+    */
     return verifierResultBuilder.build();
   }
 
diff --git a/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/EquivalentRules.java b/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/EquivalentRules.java
index f61c8916f694eff1d5cf8e2e92d48de5395aae44..20a196e32e53ba6cd9468a0f19ec9cfd9772f5ce 100644
--- a/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/EquivalentRules.java
+++ b/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/EquivalentRules.java
@@ -22,7 +22,9 @@ public class EquivalentRules extends AbstractVerifier {
   }
 
   @Override
-  protected void beforeVerifyDecision() {}
+  protected void beforeVerifyDecision() {
+    // Nothing
+  }
 
   @Override
   protected void verifyDecision(DmnDecision d) {
@@ -67,5 +69,7 @@ public class EquivalentRules extends AbstractVerifier {
   }
 
   @Override
-  protected void afterVerifyDecision() {}
+  protected void afterVerifyDecision() {
+    // Nothing
+  }
 }
diff --git a/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/IdenticalRules.java b/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/IdenticalRules.java
index c3abfa77f97d3cb477d4b7ee5bf7a9067551d8dc..4c9347ded6edabc2575f48d860888a4dcee47b9d 100644
--- a/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/IdenticalRules.java
+++ b/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/IdenticalRules.java
@@ -18,7 +18,9 @@ public class IdenticalRules extends AbstractVerifier {
   }
 
   @Override
-  protected void beforeVerifyDecision() {}
+  protected void beforeVerifyDecision() {
+    // Nothing
+  }
 
   @Override
   protected void verifyDecision(DmnDecision d) {
@@ -31,15 +33,18 @@ public class IdenticalRules extends AbstractVerifier {
   private void checkForIdenticalRules(
       List<Type> inputs, int i, List<RuleIdentifier> currentRuleIdentifiers) {
     if (i == inputs.size()) {
+      boolean differentConclusions =
+          checkDifferentConclusion(
+              currentRuleIdentifiers.get(0).getDecisionKey(), currentRuleIdentifiers);
       VerificationResult.Builder vBuilder =
           VerificationResult.getBuilder()
-              .withMessage(
-                  getMessageText(
-                      currentRuleIdentifiers,
-                      checkDifferentConclusion(
-                          currentRuleIdentifiers.get(0).getDecisionKey(), currentRuleIdentifiers)));
+              .withMessage(getMessageText(currentRuleIdentifiers, differentConclusions));
       vBuilder.addRules(currentRuleIdentifiers);
-      addVerification(vBuilder.build());
+      VerificationResult vResult = vBuilder.build();
+      if (differentConclusions) {
+        interdeterminismRules.add(vResult);
+      }
+      addVerification(vResult);
     } else {
       List<Value> currentBounds = new ArrayList<>();
       List<Value> sortedBounds =
@@ -76,9 +81,6 @@ public class IdenticalRules extends AbstractVerifier {
     }
   }
 
-  @Override
-  protected void afterVerifyDecision() {}
-
   private String getMessageText(
       List<RuleIdentifier> currentRuleIdentifiers, boolean isDifferentConclusion) {
     StringBuilder sb = new StringBuilder("Rules ");
@@ -97,4 +99,9 @@ public class IdenticalRules extends AbstractVerifier {
     }
     return sb.toString();
   }
+
+  @Override
+  protected void afterVerifyDecision() {
+    // Nothing}
+  }
 }
diff --git a/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/InterdeterminismRules.java b/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/InterdeterminismRules.java
new file mode 100644
index 0000000000000000000000000000000000000000..7694d0731daf2ffa14304b12b8761616357698cd
--- /dev/null
+++ b/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/InterdeterminismRules.java
@@ -0,0 +1,31 @@
+package de.unikoblenz.fgbks.dmn.core.verifier;
+
+import static de.unikoblenz.fgbks.dmn.core.models.VerifierType.Interdeterminism;
+
+import de.unikoblenz.fgbks.dmn.core.models.VerificationResult;
+import org.camunda.bpm.dmn.engine.DmnDecision;
+
+public class InterdeterminismRules extends AbstractVerifier {
+
+  public InterdeterminismRules() {
+    super(Interdeterminism);
+  }
+
+  @Override
+  protected void beforeVerifyDecision() {
+    // Nothing
+  }
+
+  @Override
+  protected void verifyDecision(DmnDecision d) {
+    // Nothing
+  }
+
+  @Override
+  protected void afterVerifyDecision() {
+    // just add the rules prev found in overlapping, identical or subsumption
+    for (VerificationResult verificationResult : interdeterminismRules) {
+      addVerification(verificationResult);
+    }
+  }
+}
diff --git a/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/MissingRules.java b/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/MissingRules.java
index 66fe182a13a3354b57485ce7982f1f96061e7732..e617d9f452959b925e8e837534982cd7279f360c 100644
--- a/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/MissingRules.java
+++ b/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/MissingRules.java
@@ -22,7 +22,9 @@ public class MissingRules extends AbstractVerifier {
   }
 
   @Override
-  protected void beforeVerifyDecision() {}
+  protected void beforeVerifyDecision() {
+    // Nothing
+  }
 
   @Override
   protected void verifyDecision(DmnDecision d) {
@@ -184,5 +186,7 @@ public class MissingRules extends AbstractVerifier {
   }
 
   @Override
-  protected void afterVerifyDecision() {}
+  protected void afterVerifyDecision() {
+    // Nothing
+  }
 }
diff --git a/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/OverlappingRules.java b/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/OverlappingRules.java
index eaced682b1f9fc8b471d7f52b8280977c31e4259..1d74781270a7d9dbaf39624f55572e769c677bc5 100644
--- a/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/OverlappingRules.java
+++ b/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/OverlappingRules.java
@@ -38,16 +38,18 @@ public class OverlappingRules extends AbstractVerifier {
     if (i == inputs.size()) {
       // do nothing, if there was no real overlap found prev..
       if (hasOverlap) {
+        boolean differentConclusions =
+            checkDifferentConclusion(
+                currentRuleIdentifiers.get(0).getDecisionKey(), currentRuleIdentifiers);
         VerificationResult.Builder vBuilder =
             VerificationResult.getBuilder()
-                .withMessage(
-                    getMessageText(
-                        currentRuleIdentifiers,
-                        checkDifferentConclusion(
-                            currentRuleIdentifiers.get(0).getDecisionKey(),
-                            currentRuleIdentifiers)));
+                .withMessage(getMessageText(currentRuleIdentifiers, differentConclusions));
         vBuilder.addRules(currentRuleIdentifiers);
-        addVerification(vBuilder.build());
+        VerificationResult vResult = vBuilder.build();
+        if (differentConclusions) {
+          interdeterminismRules.add(vResult);
+        }
+        addVerification(vResult);
       }
     } else {
       List<Value> currentBounds = new ArrayList<>();
@@ -142,7 +144,9 @@ public class OverlappingRules extends AbstractVerifier {
   }
 
   @Override
-  protected void afterVerifyDecision() {}
+  protected void afterVerifyDecision() {
+    // Nothing
+  }
 
   private String getMessageText(
       List<RuleIdentifier> currentRuleIdentifiers, boolean isDifferentConclusion) {
diff --git a/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/PartialReductionRules.java b/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/PartialReductionRules.java
index 15da25ef0e73cb1cb4f95bf416830d55ade54a75..83bae0c96a091bbefdc70dbb2d7d86c4fd6117ce 100644
--- a/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/PartialReductionRules.java
+++ b/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/PartialReductionRules.java
@@ -18,7 +18,9 @@ public class PartialReductionRules extends AbstractVerifier {
   }
 
   @Override
-  protected void beforeVerifyDecision() {}
+  protected void beforeVerifyDecision() {
+    // Nothing
+  }
 
   @Override
   protected void verifyDecision(DmnDecision d) {
@@ -157,5 +159,7 @@ public class PartialReductionRules extends AbstractVerifier {
   }
 
   @Override
-  protected void afterVerifyDecision() {}
+  protected void afterVerifyDecision() {
+    // Nothing
+  }
 }
diff --git a/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/SubsumptionRules.java b/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/SubsumptionRules.java
index b5f219670da39634f8e39f89aee0869e58d9eeca..c003c28b1b67e7575028dcd7901b7197601c733e 100644
--- a/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/SubsumptionRules.java
+++ b/dmn-verifier-app/src/main/java/de/unikoblenz/fgbks/dmn/core/verifier/SubsumptionRules.java
@@ -39,20 +39,23 @@ public class SubsumptionRules extends AbstractVerifier {
     if (i == inputs.size()) {
       // finish, if subsumption was found previously, than add the rules
       if (hasSubsumption && currentRuleIdentifiers.size() > currentRootSubsumptionElements.size()) {
+        boolean differentConclusions =
+            checkDifferentConclusion(
+                currentRootSubsumptionElements.get(0).getRuleIdentifier().getDecisionKey(),
+                currentRuleIdentifiers);
         VerificationResult.Builder vBuilder =
             VerificationResult.getBuilder()
                 .withMessage(
                     getMessageText(
                         currentRuleIdentifiers,
                         currentRootSubsumptionElements,
-                        checkDifferentConclusion(
-                            currentRootSubsumptionElements
-                                .get(0)
-                                .getRuleIdentifier()
-                                .getDecisionKey(),
-                            currentRuleIdentifiers)));
+                        differentConclusions));
         vBuilder.addRules(currentRuleIdentifiers);
-        addVerification(vBuilder.build());
+        VerificationResult vResult = vBuilder.build();
+        if (differentConclusions) {
+          interdeterminismRules.add(vResult);
+        }
+        addVerification(vResult);
       }
     } else {
       // get all input values from the current column, and filter with the prev. iteration