diff --git a/build.sbt b/build.sbt
index 13a20cca573a7a4da9c725045f83be66ee9a7f82..429b5512ca8973c46170656137d00acbf002d74f 100644
--- a/build.sbt
+++ b/build.sbt
@@ -1,4 +1,3 @@
-import com.simplytyped.Antlr4Plugin.autoImport.antlr4PackageName
 import sbt.Keys.{libraryDependencies, scalacOptions, version}
 
 val emfcommonVersion = "2.12.0"
@@ -55,8 +54,4 @@ lazy val generator = (project in file("."))
   ).dependsOn(
     modelmanagementprovider,
     uiProvider
-  ).enablePlugins(Antlr4Plugin)
-
-antlr4PackageName in Antlr4 := Some("org.rosi_project.model_sync.model_join.representation.parser.antlr.generated")
-antlr4GenVisitor in Antlr4 := true
-antlr4GenListener in Antlr4 := false
+  )
diff --git a/project/sbt-antlr4.sbt b/project/sbt-antlr4.sbt
deleted file mode 100644
index 7b26d1fc7b9ee12df151e57cb9e2528c1a4f8d9f..0000000000000000000000000000000000000000
--- a/project/sbt-antlr4.sbt
+++ /dev/null
@@ -1,2 +0,0 @@
-
-addSbtPlugin("com.simplytyped" % "sbt-antlr4" % "0.8.2")
diff --git a/src/main/antlr4/ModelJoin.g4 b/src/main/antlr4/ModelJoin.g4
deleted file mode 100644
index 70817b5b7a0eed652b51f26aaf916e280a5bbc90..0000000000000000000000000000000000000000
--- a/src/main/antlr4/ModelJoin.g4
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * ModelJoin.g4
- *
- * Defines the structure of our ModelJoin grammar
- *
- * Author: Rico Bergmann
- */
-grammar ModelJoin;
-
-/*
- * Parser
- */
-modeljoin : join+ EOF ;
-join : (naturaljoin | thetajoin | outerjoin) AS classres
-  ( OPENCURLYBRAKET
-    keepattributesexpr*
-    keepaggregatesexpr*
-    keepcalculatedexpr*
-    keepexpr*
-  CLOSEDCURLYBRAKET )? ;
-naturaljoin : NATURAL JOIN classres WITH classres ;
-thetajoin : THETA JOIN classres WITH classres WHERE oclcond;
-outerjoin : (leftouterjoin | rightouterjoin) OUTER JOIN classres WITH classres;
-leftouterjoin : LEFT ;
-rightouterjoin : RIGHT ;
-
-keepattributesexpr : KEEP ATTRIBUTES attrres (COMMA attrres)* ;
-keepaggregatesexpr : KEEP AGGREGATE aggrtype
-                      OPENBRAKET relattr CLOSEDBRAKET
-                      OVER classres AS attrres  ;
-keepcalculatedexpr  : KEEP CALCULATED ATTRIBUTE oclcond AS (typedattrres | attrres) ;
-keepexpr : (keeptypeexpr | keepoutgoingexpr | keepincomingexpr)
-  ( OPENCURLYBRAKET
-    keepattributesexpr*
-    keepaggregatesexpr*
-    keepcalculatedexpr*
-    keepexpr*
-  CLOSEDCURLYBRAKET)? ;
-keeptypeexpr : keepsupertypeexpr | keepsubtypeexpr ;
-keepsupertypeexpr : KEEP SUPERTYPE classres ( AS TYPE classres )? ;
-keepsubtypeexpr : KEEP SUBTYPE classres ( AS TYPE classres )? ;
-keepoutgoingexpr : KEEP OUTGOING attrres ( AS TYPE classres )? ;
-keepincomingexpr : KEEP INCOMING attrres (AS TYPE classres )? ;
-
-classres : WORD (DOT WORD)* ;
-attrres : WORD (DOT WORD)+ ;
-typedattrres  : attrres COLON WORD  ;
-relattr : WORD ;
-oclcond : (WORD | NUMBER | specialchar | anytoken | WHITESPACE | NEWLINE)+;
-aggrtype : SUM | AVG | MIN | MAX | SIZE ;
-
-specialchar : DOT
-              | OPENBRAKET
-              | CLOSEDBRAKET
-              | OPENCURLYBRAKET
-              | CLOSEDCURLYBRAKET
-              | COMMA
-              | UNDERSCORE
-              | SPECIALCHAR ;
-
-// anytoken matches all possible tokens in case their content may appear as part of some regular
-// text as well
-anytoken  : OPENBRAKET
-          | CLOSEDBRAKET
-          | OPENCURLYBRAKET
-          | CLOSEDCURLYBRAKET
-          | DOT
-          | COLON
-          | COMMA
-          | UNDERSCORE
-          | SPECIALCHAR
-
-          | JOIN
-          | NATURAL
-          | THETA
-          | WHERE
-          | OUTER
-          | RIGHT
-          | LEFT
-          | WITH
-          | AS
-
-          | KEEP
-          | ATTRIBUTES
-          | ATTRIBUTE
-          | AGGREGATE
-          | CALCULATED
-          | SUPERTYPE
-          | SUBTYPE
-          | OUTGOING
-          | INCOMING
-          | TYPE
-          | OVER
-
-          | SUM
-          | AVG
-          | MIN
-          | MAX
-          | SIZE ;
-
-/*
- * Lexer
- */
-
-fragment LOWERCASE  : [a-z]                 ;
-fragment UPPERCASE  : [A-Z]                 ;
-fragment ANYCASE    : LOWERCASE | UPPERCASE ;
-fragment DIGIT      : [0-9]                 ;
-
-OPENBRAKET        : '('         ;
-CLOSEDBRAKET      : ')'         ;
-OPENCURLYBRAKET   : '{'         ;
-CLOSEDCURLYBRAKET : '}'         ;
-DOT               : '.'         ;
-COLON             : ':'         ;
-COMMA             : ','         ;
-UNDERSCORE        : '_'         ;
-SPECIALCHAR       : [-><!="'|]  ;
-
-JOIN    : 'join'    ;
-NATURAL : 'natural' ;
-THETA   : 'theta'   ;
-WHERE   : 'where'   ;
-OUTER   : 'outer'   ;
-RIGHT   : 'right'   ;
-LEFT    : 'left'    ;
-WITH    : 'with'    ;
-AS      : 'as'      ;
-
-KEEP        : 'keep'        ;
-ATTRIBUTES  : 'attributes'  ;
-ATTRIBUTE   : 'attribute'   ;
-AGGREGATE   : 'aggregate'   ;
-CALCULATED  : 'calculated'  ;
-SUPERTYPE   : 'supertype'   ;
-SUBTYPE     : 'subtype'     ;
-OUTGOING    : 'outgoing'    ;
-INCOMING    : 'incoming'    ;
-TYPE        : 'type'        ;
-OVER        : 'over'        ;
-
-SUM   : 'sum'   ;
-AVG   : 'avg'   ;
-MIN   : 'min'   ;
-MAX   : 'max'   ;
-SIZE  : 'size'  ;
-
-WORD    : ANYCASE (ANYCASE | DIGIT | UNDERSCORE)* ;
-NUMBER  : [+-]? DIGIT+ DOT? DIGIT* ;
-
-WHITESPACE  : ' ' -> skip                   ;
-NEWLINE     : ('\r'? '\n' | '\r')+ -> skip  ;
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/AttributePath.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/core/AttributePath.java
deleted file mode 100644
index 2f28ca24b1a9e644ec9799541d88ef1d65c8e972..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/AttributePath.java
+++ /dev/null
@@ -1,147 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.core;
-
-import java.util.Objects;
-import javax.annotation.Nonnull;
-
-/**
- * An {@code AttributePath} represents a single attribute of some model class.
- * <p>
- * As <em>ModelJoin</em> does not care about types at a conceptual level, no type information is
- * stored.
- *
- * @author Rico Bergmann
- */
-public class AttributePath {
-
-  private static final String CLASS_ATTRIBUTE_DELIMITER = ".";
-
-  /**
-   * Generates a new {@code path} given the owning class as well as the attribute's name.
-   */
-  @Nonnull
-  public static AttributePath from(
-      @Nonnull ClassResource containingClass,
-      @Nonnull String attributeName) {
-    return new AttributePath(containingClass, attributeName);
-  }
-
-  /**
-   * Generates a new {@code path} given the owning class as well as the attribute.
-   */
-  @Nonnull
-  public static AttributePath from(
-      @Nonnull ClassResource containingClass,
-      @Nonnull RelativeAttribute attribute) {
-    return new AttributePath(containingClass, attribute);
-  }
-
-  public static AttributePath from(String containingClass, String attributeName) {
-    return new AttributePath(containingClass, attributeName);
-  }
-
-  /**
-   * Generates a new {@code AttributePath} by splitting up the {@code qualifiedPath} into the
-   * {@link ClassResource} and attribute portion. Therefore the {@code qualifiedPath} is expected
-   * to adhere to the following scheme: {@code [package].class.attribute}.
-   */
-  @Nonnull
-  public static AttributePath fromQualifiedPath(@Nonnull String qualifiedPath) {
-    final int splitPos = qualifiedPath.lastIndexOf(CLASS_ATTRIBUTE_DELIMITER);
-
-    if (splitPos < 0) {
-      throw new IllegalArgumentException("Missing class portion on '" + qualifiedPath + "'");
-    }
-
-    String classResourcePortion = qualifiedPath.substring(0, splitPos);
-    String attributePortion = qualifiedPath.substring(splitPos + 1);
-    return new AttributePath(ClassResource.fromQualifiedName(classResourcePortion), attributePortion);
-  }
-
-  @Nonnull
-  private final ClassResource containingClass;
-
-  @Nonnull
-  private final RelativeAttribute attribute;
-
-  public AttributePath(String containingClass, String attributeName) {
-    this.containingClass = ClassResource.fromQualifiedName(containingClass);
-    this.attribute = RelativeAttribute.of(attributeName);
-  }
-
-  /**
-   * Full constructor, parsing the attribute's name into a valid {@link RelativeAttribute}.
-   *
-   * @param containingClass the class which owns the attribute
-   * @param attributeName the attribute's name
-   */
-  public AttributePath(@Nonnull ClassResource containingClass, @Nonnull String attributeName) {
-    this.containingClass = containingClass;
-    this.attribute = RelativeAttribute.of(attributeName);
-  }
-
-  /**
-   * Full constructor.
-   *
-   * @param containingClass the class which owns the attribute
-   * @param attribute the attribute's name
-   */
-  public AttributePath(@Nonnull ClassResource containingClass, @Nonnull RelativeAttribute attribute) {
-    this.containingClass = containingClass;
-    this.attribute = attribute;
-  }
-
-  /**
-   * Creates a new {@code AttributePath} by copying another path.
-   */
-  protected AttributePath(@Nonnull AttributePath other) {
-    this.containingClass = other.getContainingClass();
-    this.attribute = other.getAttribute();
-  }
-
-  /**
-   * Provides the class which owns {@code this} attribute.
-   */
-  @Nonnull
-  public ClassResource getContainingClass() {
-    return containingClass;
-  }
-
-  /**
-   * Provides {@code this} attribute as a {@link RelativeAttribute}.
-   */
-  @Nonnull
-  public RelativeAttribute getAttribute() {
-    return attribute;
-  }
-
-  /**
-   * Provides the name of {@code this} attribute.
-   */
-  @Nonnull
-  public String getAttributeName() {
-    return attribute.getAttributeName();
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (!(o instanceof AttributePath)) {
-      return false;
-    }
-    AttributePath that = (AttributePath) o;
-    return containingClass.equals(that.containingClass) &&
-        attribute.equals(that.attribute);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(containingClass, attribute);
-  }
-
-  @Override
-  public String toString() {
-    return containingClass.toString() + "." + attribute;
-  }
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/ClassResource.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/core/ClassResource.java
deleted file mode 100644
index 7143ad71f59935a361fbb255c576ad208ae7a1d3..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/ClassResource.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.core;
-
-import javax.annotation.Nonnull;
-
-/**
- * A {@code ClassResource} represents a fully-qualified reference to some class to be used in a
- * join. This class merely exist to emphasize that some resource actually represents a class and
- * thus provides a nicer (i.e. better named) interface to query for the resource's fields.
- * <p>
- * In difference to a {@link ResourcePath}, instances of this class will drop the {@code .java}
- * ending of the file name if referenced from the file system.
- *
- * @author Rico Bergmann
- */
-public class ClassResource extends ResourcePath {
-
-  /**
-   * Generates a new {@code path} given the path to its containing <em>package</em> and the name of
-   * the class which should be referenced.
-   */
-  @Nonnull
-  public static ClassResource from(@Nonnull String packagePath, @Nonnull String className) {
-    return new ClassResource(packagePath, className);
-  }
-
-  /**
-   * @see ResourcePath#parse(String)
-   */
-  @Nonnull
-  public static ClassResource fromQualifiedName(@Nonnull String qualifiedClass) {
-    /*
-     * A class resource is just a better representation of a class (in difference to just _some_
-     * kind of resource) but works just the same - thus we will re-use all the parsing logic from
-     * the ResourcePath
-     */
-    ResourcePath parsedResource = ResourcePath.parse(qualifiedClass);
-    return new ClassResource(parsedResource.resourcePath, parsedResource.resourceName);
-  }
-
-  /**
-   * @see ResourcePath#parseAsFileSystemPath(String)
-   */
-  @Nonnull
-  public static ClassResource fromFileSystem(@Nonnull String fullPath) {
-    /*
-     * A class resource is just a better representation of a class (in difference to just _some_
-     * kind of resource) but works just the same - thus we will re-use all the parsing logic from
-     * the ResourcePath
-     */
-    ResourcePath parsedResource = ResourcePath.parseAsFileSystemPath(dropFileTypeEnding(fullPath));
-    return new ClassResource(parsedResource.resourcePath, parsedResource.resourceName);
-  }
-
-  /**
-   * Deletes the {@code .java} ending from a resource name.
-   */
-  private static String dropFileTypeEnding(String fullPath) {
-    return fullPath.replaceAll("\\.java$", "");
-  }
-
-  /**
-   * Full constructor.
-   *
-   * @param containingPackage the path to the package to which the class belongs
-   * @param className the name of the class
-   */
-  public ClassResource(@Nonnull String containingPackage, @Nonnull String className) {
-    super(containingPackage, className);
-  }
-
-  /**
-   * Provides the name of the class represented by {@code this} resource.
-   */
-  @Nonnull
-  public String getClassName() {
-    return resourceName;
-  }
-
-  /**
-   * Provides the package that contains the class represented by {@code this} resource.
-   */
-  @Nonnull
-  public String getPackage() {
-    return resourcePath;
-  }
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/OCLConstraint.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/core/OCLConstraint.java
deleted file mode 100644
index 6f8afef2b4ba2623225ac2f1aed8ed72a6d838f5..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/OCLConstraint.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.core;
-
-import javax.annotation.Nonnull;
-
-/**
- * An {@code OCLConstraint} specifies some predicate on (possibly multiple) models that have to hold
- * under certain conditions.
- * <p>
- * This class is a specialization of an arbitrary {@link OCLStatement} for statements, that
- * evaluate to a boolean values.
- *
- * @author Rico Bergmann
- */
-public class OCLConstraint extends OCLStatement {
-
-  /**
-   * Generates a new constraint with the given content.
-   */
-  @Nonnull
-  public static OCLConstraint of(@Nonnull String content) {
-    return new OCLConstraint(content);
-  }
-
-  /**
-   * Full constructor.
-   *
-   * @param content the actual constraint
-   */
-  public OCLConstraint(@Nonnull String content) {
-    super(content);
-  }
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/OCLStatement.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/core/OCLStatement.java
deleted file mode 100644
index 5acfc57b4c2c5ef660e5e9ee2ff6cc51a5d819dd..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/OCLStatement.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.core;
-
-import java.util.Objects;
-import javax.annotation.Nonnull;
-
-/**
- * An {@code OCLStatement} is a simple expression written in the {@code Object Constraint Language}.
- * <p>
- * This class simply wraps an arbitrary OCL expression. No further checks or the like are performed.
- *
- * @author Rico Bergmann
- * @see <a href="https://www.omg.org/spec/OCL/">OMG OCL specification</a>
- */
-public class OCLStatement {
-
-  /**
-   * Creates a new statement with the given {@code content}.
-   */
-  @Nonnull
-  public static OCLStatement of(@Nonnull String content) {
-    return new OCLStatement(content);
-  }
-
-  @Nonnull
-  protected final String content;
-
-  /**
-   * Full constructor.
-   *
-   * @param content the actual expression
-   */
-  public OCLStatement(@Nonnull String content) {
-    this.content = content;
-  }
-
-  /**
-   * Provides the actual statement as a {@code String}.
-   */
-  public String get() {
-    return content;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-    OCLStatement that = (OCLStatement) o;
-    return content.equals(that.content);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(content);
-  }
-
-  @Override
-  public String toString() {
-    return content;
-  }
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/RelativeAttribute.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/core/RelativeAttribute.java
deleted file mode 100644
index d3e002c63df945d8c681a987390ffa2b1b3150f3..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/RelativeAttribute.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.core;
-
-import java.util.Objects;
-import javax.annotation.Nonnull;
-
-/**
- * A {@code RelativeAttribute} represents a member of some class.
- * <p>
- * In difference to the {@link AttributePath} this class does not retain any information about the
- * class to which it belongs.
- *
- * @author Rico Bergmann
- */
-public class RelativeAttribute {
-
-  /**
-   * Extracts the attribute from a qualified {@link AttributePath}.
-   */
-  @Nonnull
-  public static RelativeAttribute from(@Nonnull AttributePath attributePath) {
-    return new RelativeAttribute(attributePath.getAttributeName());
-  }
-
-  /**
-   * Generates a new {@code RelativeAttribute} with the given name.
-   */
-  @Nonnull
-  public static RelativeAttribute of(@Nonnull String attributeName) {
-    if (!attributeName.matches(ATTRIBUTE_NAME_REGEX)) {
-      throw new IllegalArgumentException("Not a valid attribute name: " + attributeName);
-    }
-    return new RelativeAttribute(attributeName);
-  }
-
-  private static final String ATTRIBUTE_NAME_REGEX = "^[a-zA-Z_]\\w*$";
-
-  @Nonnull
-  private final String attributeName;
-
-  /**
-   * Full constructor.
-   *
-   * @param attributeName the name of the attribute to generate
-   */
-  public RelativeAttribute(@Nonnull String attributeName) {
-    this.attributeName = attributeName;
-  }
-
-  /**
-   * Provides the name of the represented attribute.
-   */
-  @Nonnull
-  public String getAttributeName() {
-    return attributeName;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-    RelativeAttribute that = (RelativeAttribute) o;
-    return attributeName.equals(that.attributeName);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(attributeName);
-  }
-
-  @Override
-  public String toString() {
-    return attributeName;
-  }
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/ResourcePath.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/core/ResourcePath.java
deleted file mode 100644
index d4f99857bc7c86cb284681e6853b86ae2f52a677..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/ResourcePath.java
+++ /dev/null
@@ -1,154 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.core;
-
-import java.io.File;
-import java.util.Objects;
-import javax.annotation.Nonnull;
-
-/**
- * A {@code ResourcePath} represents a fully-qualified name of some model element to be used in a
- * join.
- *
- * @author Rico Bergmann
- */
-public class ResourcePath {
-
-  /**
-   * Generates a new {@code path} given the path to its containing <em>package</em> and the name of
-   * the resource which should be referenced.
-   */
-  @Nonnull
-  public static ResourcePath from(@Nonnull String packagePath, @Nonnull String resourceName) {
-    return new ResourcePath(packagePath, resourceName);
-  }
-
-  /**
-   * Generates a new {@code path} given its fully-qualified name.
-   *
-   * @param qualifiedResourcePath the path. It is expected to conform to the format {@code
-   *     pathToResource.resourceName}
-   */
-  @Nonnull
-  public static ResourcePath parse(@Nonnull String qualifiedResourcePath) {
-    if (qualifiedResourcePath.equals(".")) {
-      throw new IllegalArgumentException(
-          "Not a valid resource path: '" + qualifiedResourcePath + "'");
-    }
-
-    int splitPos = qualifiedResourcePath.lastIndexOf(".");
-
-    String packagePath;
-    if (splitPos == -1) {
-      packagePath = "";
-    } else {
-      packagePath = qualifiedResourcePath.substring(0, splitPos);
-    }
-
-    String resourceName = qualifiedResourcePath.substring(splitPos + 1);
-    return new ResourcePath(packagePath, resourceName);
-  }
-
-  /**
-   * Generates a new {@code path} given its fully-qualified name.
-   * <p>
-   * The name will be interpreted as some location on the file system (that is as {@code
-   * /path/to/resource}). However, both {@code \} as well as {@code /} will be accepted as path
-   * separators.
-   *
-   * @param qualifiedResourcePath the path. It is expected to conform to the format {@code
-   *     pathToResource/resourceName}
-   */
-  public static ResourcePath parseAsFileSystemPath(@Nonnull String qualifiedResourcePath) {
-    return parse(toPackageStylePath(qualifiedResourcePath));
-  }
-
-  /**
-   * Converts a path as used by the file system to the corresponding path as used in a Java package.
-   */
-  protected static String toPackageStylePath(@Nonnull String fileSystemResourcePath) {
-    return fileSystemResourcePath.replaceAll("[\\\\/]", ".");
-  }
-
-  @Nonnull
-  protected final String resourcePath;
-
-  @Nonnull
-  protected final String resourceName;
-
-  /**
-   * Full constructor.
-   *
-   * @param resourcePath the path to the directory/package in which the resource resides
-   * @param resourceName the name of the class (or other resource)
-   */
-  public ResourcePath(@Nonnull String resourcePath, @Nonnull String resourceName) {
-    if (resourceName.isEmpty()) {
-      throw new IllegalArgumentException("Resource name may not be empty");
-    }
-    this.resourcePath = resourcePath;
-    this.resourceName = resourceName;
-  }
-
-  /**
-   * Provides the path to the directory/package in which {@code this} resource resides. The path
-   * will be in "Java-package style", i.e. its components will be separated by {@code .}.
-   */
-  @Nonnull
-  public String getResourcePath() {
-    return resourcePath;
-  }
-
-  /**
-   * Provides the name of the resource which is represented by {@code this} path.
-   * <p>
-   * The name is relative to the containing directory/package.
-   */
-  @Nonnull
-  public String getResourceName() {
-    return resourceName;
-  }
-
-  /**
-   * Converts {@code this} path to {@code String}. It will match the format {@code package.name}.
-   */
-  @Nonnull
-  public String get() {
-    return this.toString();
-  }
-
-  /**
-   * Converts {@code this} path to a {@code String}, treating it as some path on the file system.
-   * <p>
-   * The components of the path will be separated by the platform-dependent separator for the
-   * current platform. That is, its result may vary depending on the OS on which it is run.
-   */
-  @Nonnull
-  public String getAsFileSystemPath() {
-    return this.toString().replaceAll("\\.", File.pathSeparator);
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-    ResourcePath that = (ResourcePath) o;
-    return this.resourcePath.equals(that.resourcePath) &&
-        this.resourceName.equals(that.resourceName);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(resourcePath, resourceName);
-  }
-
-  @Override
-  public String toString() {
-    if (resourcePath.isEmpty()) {
-      return resourceName;
-    }
-    return resourcePath + "." + resourceName;
-  }
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/TypedAttributePath.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/core/TypedAttributePath.java
deleted file mode 100644
index 0384a2acf0bdb6fdacbbeb050a89c035d9a9fad1..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/TypedAttributePath.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.core;
-
-import java.util.Objects;
-import javax.annotation.Nonnull;
-
-/**
- * A {@code TypedAttributePath} extends a default {@link AttributePath} by adding type information,
- * i.e. adding information about the type of the object the path references.
- * <p>
- * As we do not have any knowledge about the actual classes that are represented by paths we may
- * not validate, whether the given type indeed matches the attribute's type.
- *
- * @author Rico Bergmann
- */
-public class TypedAttributePath extends AttributePath {
-
-  private static final String PATH_TYPE_SEPARATOR = ":";
-
-  /**
-   * Creates a new {@code TypedAttributePath} by combining the provided path and type information.
-   */
-  @Nonnull
-  public static TypedAttributePath of(@Nonnull AttributePath path, @Nonnull ClassResource type) {
-    return new TypedAttributePath(path, type);
-  }
-
-  /**
-   * Generates a new {@code TypedAttributePath} by splitting up the given path into its path and
-   * type portion. The {@code qualifiedTypedPath} is expected to match the format {@code path:type},
-   * where {@code path} may be parsed using {@link AttributePath#fromQualifiedPath(String)} and type
-   * may be parsed using {@link ClassResource#fromQualifiedName(String)}.
-   */
-  @Nonnull
-  public static TypedAttributePath fromQualifiedTypedPath(@Nonnull String qualifiedTypedPath) {
-    final int pathTypeSplitPos = qualifiedTypedPath.lastIndexOf(PATH_TYPE_SEPARATOR);
-
-    if (pathTypeSplitPos < 0) {
-      throw new IllegalArgumentException("Missing type portion on '" + qualifiedTypedPath + "'");
-    }
-
-    final String qualifiedPath = qualifiedTypedPath.substring(0, pathTypeSplitPos);
-    final String type = qualifiedTypedPath.substring(pathTypeSplitPos + 1);
-    return new TypedAttributePath(AttributePath.fromQualifiedPath(qualifiedPath), ClassResource.fromQualifiedName(type));
-  }
-
-  @Nonnull
-  private final ClassResource type;
-
-  /**
-   * Full constructor.
-   *
-   * @param path the attribute
-   * @param type the attribute's type
-   */
-  public TypedAttributePath(
-      @Nonnull AttributePath path,
-      @Nonnull ClassResource type) {
-    super(path);
-    this.type = type;
-  }
-
-  /**
-   * Provides the type of {@code this} attribute.
-   */
-  @Nonnull
-  public ClassResource getType() {
-    return type;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (!(o instanceof TypedAttributePath)) {
-      return false;
-    }
-    if (!super.equals(o)) {
-      return false;
-    }
-    TypedAttributePath that = (TypedAttributePath) o;
-    return type.equals(that.type);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(super.hashCode(), type);
-  }
-
-  @Override
-  public String toString() {
-    return super.toString() + PATH_TYPE_SEPARATOR + type.toString();
-  }
-
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/CompoundKeepExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/CompoundKeepExpression.java
deleted file mode 100644
index 1e253dafd1feee21a329b2a2f65b4cb47488627f..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/CompoundKeepExpression.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.grammar;
-
-import java.util.List;
-import javax.annotation.Nonnull;
-
-/**
- * A {@code CompoundKeepExpression} is a special kind of {@code KeepExpression} which in turn may
- * contain a number of other {@code KeepExpression}s.
- *
- * @author Rico Bergmann
- */
-public abstract class CompoundKeepExpression extends KeepExpression {
-
-  /**
-   * Provides all the keep expressions that this expression is build of.
-   */
-  @Nonnull
-  public abstract List<KeepExpression> getKeeps();
-
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/JoinExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/JoinExpression.java
deleted file mode 100644
index ecdccf901a9aa31d861a66f11afdad9c78ba96e3..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/JoinExpression.java
+++ /dev/null
@@ -1,204 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.grammar;
-
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Objects;
-import javax.annotation.Nonnull;
-import org.rosi_project.model_sync.model_join.representation.core.ClassResource;
-
-/**
- * A {@code JoinExpression} combines two classes of the source models and
- * generates a new view derived from them.
- * <p>
- * At a conceptual level, these classes are referred to as the {@code left} and
- * {@code right} class.
- * <p>
- * Other than the classes to combine, each join also consists of a number of
- * {@link KeepExpression}s which contain the fields which should form the
- * resulting class as well as information on how to set their values.
- * <p>
- * As there are a number of different joins available, this class is left
- * {@code abstract} with subclasses to represent the specific joins.
- *
- * @author Rico Bergmann
- * @see NaturalJoinExpression
- * @see OuterJoinExpression
- * @see ThetaJoinExpression
- */
-public abstract class JoinExpression implements Iterable<KeepExpression> {
-
-	/**
-	 * The {@code JoinType} defines which rules should be applied when
-	 * performing the join.
-	 */
-	public enum JoinType {
-
-		/**
-		 * The {@code natural join} combines two classes based on attributes
-		 * with equal name and type.
-		 *
-		 * @see NaturalJoinExpression
-		 */
-		NATURAL,
-
-		/**
-		 * The {@code outer join} works like the {@link #NATURAL} one, but
-		 * leaves instances from one class with no corresponding instance in the
-		 * other class according to the {@code outer join
-		 * type}. See the subclass for details.
-		 *
-		 * @see OuterJoinExpression
-		 */
-		OUTER,
-
-		/**
-		 * The {@code theta join} is more general than the {@link #NATURAL} and
-		 * {@link #OUTER} one as it enables an arbitrary criteria to define
-		 * whether two instances are "joinable" or not.
-		 *
-		 * @see ThetaJoinExpression
-		 */
-		THETA
-	}
-
-	@Nonnull
-	protected final ClassResource left;
-
-	@Nonnull
-	protected final ClassResource right;
-
-	@Nonnull
-	protected final ClassResource target;
-
-	@Nonnull
-	protected final List<KeepExpression> keeps;
-
-	/**
-	 * Full constructor.
-	 *
-	 * @param left
-	 *            the left class to use in the join
-	 * @param right
-	 *            the right class to use in the join
-	 * @param target
-	 *            the name of the resulting view
-	 * @param keeps
-	 *            the keep statements in the join
-	 */
-	protected JoinExpression(@Nonnull ClassResource left, @Nonnull ClassResource right, @Nonnull ClassResource target,
-			@Nonnull List<KeepExpression> keeps) {
-
-		this.left = left;
-		this.right = right;
-		this.target = target;
-		this.keeps = keeps;
-	}
-
-	/**
-	 * Proof if the right and the left class path are equals.
-	 * @return result value
-	 */
-	public boolean isSameElement() {
-		if (left.getResourceName().equals(right.getResourceName())
-				&& left.getResourcePath().equals(right.getResourcePath())) {
-			return true;
-		}
-		return false;
-	}
-
-	/**
-	 * Provides the based class used in {@code this} join. Only important for
-	 * outer join in other cases always Left.
-	 */
-	@Nonnull
-	public ClassResource getBaseModel() {
-		return this.getLeft();
-	}
-
-	/**
-	 * Provides the other class used in {@code this} join. Only important for
-	 * outer join in other cases always Right.
-	 */
-	@Nonnull
-	public ClassResource getOtherModel() {
-		return this.getRight();
-	}
-
-	/**
-	 * Provides the left class used in {@code this} join.
-	 */
-	@Nonnull
-	public ClassResource getLeft() {
-		return left;
-	}
-
-	/**
-	 * Provides the right class used in {@code this} join.
-	 */
-	@Nonnull
-	public ClassResource getRight() {
-		return right;
-	}
-
-	/**
-	 * Provides the name of the class resulting from {@code this} join.
-	 */
-	@Nonnull
-	public ClassResource getTarget() {
-		return target;
-	}
-
-	/**
-	 * Provides the {@code keep} statements that should be used to build the
-	 * resulting class.
-	 */
-	@Nonnull
-	public Iterable<KeepExpression> getKeeps() {
-		return keeps;
-	}
-
-	public List<KeepExpression> getKeepsList() {
-		return Collections.unmodifiableList(keeps);
-	}
-
-	/**
-	 * Provides the type of {@code this} join.
-	 */
-	@Nonnull
-	public abstract JoinType getType();
-
-	/**
-	 * Provides the type of {@code this} join as a non-technical {@code String}.
-	 */
-	@Nonnull
-	abstract String getJoinTypeAsString();
-
-	@Nonnull
-	@Override
-	public Iterator<KeepExpression> iterator() {
-		return keeps.iterator();
-	}
-
-	@Override
-	public boolean equals(Object o) {
-		if (this == o) {
-			return true;
-		}
-		if (o == null || getClass() != o.getClass()) {
-			return false;
-		}
-		JoinExpression that = (JoinExpression) o;
-		return this.target.equals(that.target);
-	}
-
-	@Override
-	public int hashCode() {
-		return Objects.hash(target);
-	}
-
-	@Override
-	public String toString() {
-		return getJoinTypeAsString() + " " + left.toString() + " with " + right.toString() + " as " + target.toString();
-	}
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepAggregateExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepAggregateExpression.java
deleted file mode 100644
index d0da5aa0b03a4d87b7cacf86d1d7c8442e577eb1..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepAggregateExpression.java
+++ /dev/null
@@ -1,261 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.grammar;
-
-import java.util.Objects;
-import javax.annotation.Nonnull;
-import org.rosi_project.model_sync.model_join.representation.core.AttributePath;
-import org.rosi_project.model_sync.model_join.representation.core.RelativeAttribute;
-
-/**
- * A {@code KeepAggregateExpression} adds an attribute to some join by calculating an aggregation on
- * the referenced collection of numerical values. The possible aggregation operations are equal to
- * those provided by the SQL programming language.
- * <p>
- * The aggregate's result will in turn be some numerical value.
- *
- * @author Rico Bergmann
- */
-public class KeepAggregateExpression extends KeepExpression {
-
-  /**
-   * The {@code AggregationType} defines what aggregation should be performed.
-   */
-  public enum AggregationType {
-
-    /**
-     * The attribute's value should be the sum of all the referenced values.
-     */
-    SUM,
-
-    /**
-     * The attribute's value should be the average value of all the referenced values.
-     */
-    AVG,
-
-    /**
-     * The attribute's value should be the minimum value of all the referenced values.
-     */
-    MIN,
-
-    /**
-     * The attribute's value should be the maximum value of all the referenced values.
-     */
-    MAX,
-
-    /**
-     * The attribute's value should be the number of referenced elements.
-     */
-    SIZE
-  }
-
-  /**
-   * The {@code AggregateBuilder} enables the construction of new {@link KeepAggregateExpression}s
-   * through a nice and fluent interface.
-   *
-   * @author Rico Bergmann
-   */
-  public static class AggregateBuilder {
-
-    @Nonnull
-    private final AggregationType aggregationType;
-
-    @Nonnull
-    private final RelativeAttribute aggregatedAttribute;
-
-    @Nonnull
-    private AttributePath source;
-
-    /**
-     * Full constructor.
-     *
-     * @param aggregationType the aggregation operation that should be performed
-     * @param aggregatedAttribute the attribute on which the aggregation should be performed
-     */
-    AggregateBuilder(@Nonnull AggregationType aggregationType,
-        @Nonnull RelativeAttribute aggregatedAttribute) {
-      this.aggregationType = aggregationType;
-      this.aggregatedAttribute = aggregatedAttribute;
-    }
-
-    /**
-     * Specifies the reference destination that provides the attribute to join.
-     * <p>
-     * Suppose the following example:
-     * <pre>
-     * {@code
-     *  class City {
-     *    List<Street> streets;
-     *  }
-     *
-     *  class Street {
-     *    int length;
-     *  }
-     * }
-     * </pre>
-     * If one was to calculate the average length of all streets per city, the following aggregation
-     * could be used: {@code keep aggregate avg(length) over City.streets as avgStreetLength}. In
-     * this case, {@code City.streets} is the wanted reference destination as it provides the {@code
-     * length} attribute which should be used for the aggregation.
-     */
-    @Nonnull
-    public AggregateBuilder over(@Nonnull AttributePath source) {
-      this.source = source;
-      return this;
-    }
-
-    /**
-     * Specifies the name of the aggregation attribute in the target join.
-     */
-    @Nonnull
-    public KeepAggregateExpression as(@Nonnull AttributePath target) {
-      return new KeepAggregateExpression(aggregationType, aggregatedAttribute, source, target);
-    }
-  }
-
-  /**
-   * Generates a new {@code keep aggregate} expression that sums up the referenced values.
-   */
-  @Nonnull
-  public static AggregateBuilder sum(@Nonnull RelativeAttribute attribute) {
-    return new AggregateBuilder(AggregationType.SUM, attribute);
-  }
-
-  /**
-   * Generates a new {@code keep aggregate} expression that calculates the average value of the
-   * referenced values.
-   */
-  @Nonnull
-  public static AggregateBuilder avg(@Nonnull RelativeAttribute attribute) {
-    return new AggregateBuilder(AggregationType.AVG, attribute);
-  }
-
-  /**
-   * Generates a new {@code keep aggregate} expression that provides the minimum value of the
-   * referenced values.
-   */
-  @Nonnull
-  public static AggregateBuilder min(@Nonnull RelativeAttribute attribute) {
-    return new AggregateBuilder(AggregationType.MIN, attribute);
-  }
-
-  /**
-   * Generates a new {@code keep aggregate} expression that provides the maximum value of the
-   * referenced values.
-   */
-  @Nonnull
-  public static AggregateBuilder max(@Nonnull RelativeAttribute attribute) {
-    return new AggregateBuilder(AggregationType.MAX, attribute);
-  }
-
-  /**
-   * Generates a new {@code keep aggregate} expression that counts the number of values that are
-   * referenced.
-   */
-  @Nonnull
-  public static AggregateBuilder size(@Nonnull RelativeAttribute attribute) {
-    return new AggregateBuilder(AggregationType.SIZE, attribute);
-  }
-
-  @Nonnull
-  private final AggregationType aggregation;
-
-  @Nonnull
-  private final RelativeAttribute aggregatedAttribute;
-
-  @Nonnull
-  private final AttributePath source;
-
-  @Nonnull
-  private final AttributePath target;
-
-  /**
-   * Full constructor.
-   *
-   * @param aggregation the aggregation operation that should be performed
-   * @param aggregatedAttribute the attribute on which the aggregation should be performed
-   * @param source the field which provides the {@code aggregatedAttribute}. Therefore this
-   *     attribute has to be multi-valued.
-   * @param target the name of the attribute under which the aggregation result should be
-   *     available in the join
-   */
-  public KeepAggregateExpression(
-      @Nonnull AggregationType aggregation,
-      @Nonnull RelativeAttribute aggregatedAttribute,
-      @Nonnull AttributePath source,
-      @Nonnull AttributePath target) {
-    this.aggregation = aggregation;
-    this.aggregatedAttribute = aggregatedAttribute;
-    this.source = source;
-    this.target = target;
-  }
-
-  /**
-   * Provides the aggregation operation {@code this} expression will perform.
-   */
-  @Nonnull
-  public AggregationType getAggregation() {
-    return aggregation;
-  }
-
-  /**
-   * Provides the attribute that will be aggregated. As all {@link AggregationType aggregation
-   * operations} are defined on numerical values, this attribute in turn has to be of numerical
-   * type.
-   */
-  @Nonnull
-  public RelativeAttribute getAggregatedAttribute() {
-    return aggregatedAttribute;
-  }
-
-  /**
-   * Provides the field which contains the {@link #getAggregatedAttribute() aggregated attribute}.
-   * As an aggregation will - by definition - be performed upon an arbitrary number of values, this
-   * attribute has to be some kind of collection.
-   */
-  @Nonnull
-  public AttributePath getSource() {
-    return source;
-  }
-
-  /**
-   * Provides the attribute under which the result of {@code this} aggregation should be made
-   * available.
-   */
-  @Nonnull
-  public AttributePath getTarget() {
-    return target;
-  }
-
-  @Override
-  public void accept(@Nonnull KeepExpressionVisitor visitor) {
-    visitor.visit(this);
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-    KeepAggregateExpression that = (KeepAggregateExpression) o;
-    return aggregation == that.aggregation &&
-        aggregatedAttribute.equals(that.aggregatedAttribute) &&
-        source.equals(that.source) &&
-        target.equals(that.target);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(aggregation, aggregatedAttribute, source, target);
-  }
-
-  @Override
-  public String toString() {
-    String aggregationOperation = aggregation.toString().toLowerCase();
-    return "keep aggregate " //
-        + aggregationOperation + "(" + aggregatedAttribute + ") " //
-        + "over" + source //
-        + " as " + target;
-  }
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepAttributesExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepAttributesExpression.java
deleted file mode 100644
index 99cdb8109e16e584442425b0eac0aceefbe49337..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepAttributesExpression.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.grammar;
-
-import com.google.common.collect.Lists;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import javax.annotation.Nonnull;
-import org.rosi_project.model_sync.model_join.representation.core.AttributePath;
-
-/**
- * A {@code KeepAttributesExpression} simply retains a number of attributes from arbitrary source
- * classes and includes them in the target join. The attributes' name and type will be left
- * unchanged.
- *
- * @author Rico Bergmann
- */
-public class KeepAttributesExpression extends KeepExpression {
-
-  /**
-   * Generates a new keep expression for a number of attributes.
-   */
-  @Nonnull
-  public static KeepAttributesExpression keepAttributes(@Nonnull AttributePath firstAttribute,
-      @Nonnull AttributePath... moreAttributes) {
-    List<AttributePath> attributes = Lists.newArrayList(moreAttributes);
-    attributes.add(0, firstAttribute);
-    return new KeepAttributesExpression(attributes);
-  }
-
-  @Nonnull
-  private final List<AttributePath> attributes;
-
-  /**
-   * Full constructor.
-   *
-   * @param attributes the attributes for which the expression should be created
-   */
-  public KeepAttributesExpression(@Nonnull List<AttributePath> attributes) {
-    this.attributes = attributes;
-  }
-
-  /**
-   * Provides the attributes that should be retained in the join.
-   * <p>
-   * The returned {@code List} is a shallow copy of the attributes in {@code this} expression.
-   */
-  @Nonnull
-  public List<AttributePath> getAttributes() {
-    return new ArrayList<>(attributes);
-  }
-
-  @Override
-  public void accept(@Nonnull KeepExpressionVisitor visitor) {
-    visitor.visit(this);
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-    KeepAttributesExpression that = (KeepAttributesExpression) o;
-    return this.attributes.equals(that.attributes);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(attributes);
-  }
-
-  @Override
-  public String toString() {
-    return "keep attributes " + attributes.stream() //
-        .map(AttributePath::toString) //
-        .reduce((firstAttribute, secondAttribute) -> firstAttribute + ", " + secondAttribute) //
-        .orElseThrow(() -> new IllegalStateException(
-            "A keep attribute expression has to keep at least one attribute"));
-  }
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepCalculatedExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepCalculatedExpression.java
deleted file mode 100644
index 19a1a22247fbbb23dcbcb582746b528897fc5423..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepCalculatedExpression.java
+++ /dev/null
@@ -1,125 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.grammar;
-
-import java.util.Objects;
-import javax.annotation.Nonnull;
-import org.rosi_project.model_sync.model_join.representation.core.AttributePath;
-import org.rosi_project.model_sync.model_join.representation.core.OCLStatement;
-import org.rosi_project.model_sync.model_join.representation.core.TypedAttributePath;
-
-/**
- * A {@code KeepCalculatedExpression} adds an attribute to some join by evaluating an arbitrary
- * {@link OCLStatement OCL statement}.
- * <p>
- * This is the most general kind of {@link KeepExpression} as all other expressions may be expressed
- * in OCL as well.
- *
- * @author Rico Bergmann
- * @see OCLStatement
- */
-public class KeepCalculatedExpression extends KeepExpression {
-
-  /**
-   * The {@code KeepCalculatedBuilder} enables the construction of new {@link
-   * KeepCalculatedExpression}s through a nice and fluent interface.
-   *
-   * @author Rico Bergmann
-   */
-  public static class KeepCalculatedBuilder {
-
-    @Nonnull
-    private final OCLStatement calculationRule;
-
-    /**
-     * Full constructor.
-     *
-     * @param calculationRule the OCL statement that should be used to calculate the attribute's
-     *     value.
-     */
-    KeepCalculatedBuilder(@Nonnull OCLStatement calculationRule) {
-      this.calculationRule = calculationRule;
-    }
-
-    /**
-     * Specifies the name of the attribute in the target join.
-     */
-    @Nonnull
-    public KeepCalculatedExpression as(@Nonnull TypedAttributePath target) {
-      return new KeepCalculatedExpression(calculationRule, target);
-    }
-  }
-
-  /**
-   * Generates a new {@code keep calculated} expression.
-   */
-  @Nonnull
-  public static KeepCalculatedBuilder keepCalculatedAttribute(
-      @Nonnull OCLStatement calculationRule) {
-    return new KeepCalculatedBuilder(calculationRule);
-  }
-
-  @Nonnull
-  private final OCLStatement calculationRule;
-
-  @Nonnull
-  private final TypedAttributePath target;
-
-  /**
-   * Full constructor.
-   *
-   * @param calculationRule the OCL statement that should be used to calculate the attribute's
-   *     value
-   * @param target the name of the attribute under which the aggregation result should be
-   *     available in the join
-   */
-  public KeepCalculatedExpression(
-      @Nonnull OCLStatement calculationRule,
-      @Nonnull TypedAttributePath target) {
-    this.calculationRule = calculationRule;
-    this.target = target;
-  }
-
-  /**
-   * Provides the OCL expression that is used to determine the value of {@code this} attribute.
-   */
-  @Nonnull
-  public OCLStatement getCalculationRule() {
-    return calculationRule;
-  }
-
-  /**
-   * Provides the attribute under which the result of {@code this} calculation should be made
-   * available.
-   */
-  @Nonnull
-  public TypedAttributePath getTarget() {
-    return target;
-  }
-
-  @Override
-  public void accept(@Nonnull KeepExpressionVisitor visitor) {
-    visitor.visit(this);
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-    KeepCalculatedExpression that = (KeepCalculatedExpression) o;
-    return calculationRule.equals(that.calculationRule) &&
-        target.equals(that.target);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(calculationRule, target);
-  }
-
-  @Override
-  public String toString() {
-    return "keep calculated attribute " + calculationRule + " as " + target;
-  }
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepExpression.java
deleted file mode 100644
index bd879001f642b3dc1a5beef04e196f86534e97ab..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepExpression.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.grammar;
-
-import javax.annotation.Nonnull;
-
-/**
- * A {@code KeepExpression} configures the resulting model of a join.
- * <p>
- * This mostly means retaining some attributes or calculating their value but may also include
- * maintaining references to other classes.
- *
- * @author Rico Bergmann
- */
-public abstract class KeepExpression {
-
-  /**
-   * The {@code visitor} enables the execution of arbitrary algorithms on {@code KeepExpression}s
-   * without taking care of the actual traversal of the expression tree.
-   */
-  public interface KeepExpressionVisitor {
-
-    /**
-     * Runs the algorithm as appropriate for {@link KeepAggregateExpression}s.
-     */
-    void visit(@Nonnull KeepAggregateExpression expression);
-
-    /**
-     * Runs the algorithm as appropriate for {@link KeepAttributesExpression}s.
-     */
-    void visit(@Nonnull KeepAttributesExpression expression);
-
-    /**
-     * Runs the algorithm as appropriate for {@link KeepCalculatedExpression}s.
-     */
-    void visit(@Nonnull KeepCalculatedExpression expression);
-
-    /**
-     * Runs the algorithm as appropriate for {@link KeepReferenceExpression}s.
-     */
-    void visit(@Nonnull KeepReferenceExpression expression);
-
-    /**
-     * Runs the algorithm as appropriate for {@link KeepSubTypeExpression}s.
-     */
-    void visit(@Nonnull KeepSubTypeExpression expression);
-
-    /**
-     * Runs the algorithm as appropriate for {@link KeepSuperTypeExpression}s.
-     */
-    void visit(@Nonnull KeepSuperTypeExpression expression);
-
-  }
-
-  // TODO `as` statements may be omitted !?!? ... (╯°□°)╯︵ ┻━┻
-
-  /**
-   * Applies a {@code visitor} to {@code this} expression structure.
-   */
-  public abstract void accept(@Nonnull KeepExpressionVisitor visitor);
-
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepReferenceExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepReferenceExpression.java
deleted file mode 100644
index 5d6f0f32924f2f495b21b9ab3107dcbf15c044b2..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepReferenceExpression.java
+++ /dev/null
@@ -1,223 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.grammar;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import javax.annotation.Nonnull;
-import org.rosi_project.model_sync.model_join.representation.core.AttributePath;
-import org.rosi_project.model_sync.model_join.representation.core.ClassResource;
-import org.rosi_project.model_sync.model_join.representation.util.Assert;
-
-// TODO the Xtext grammar also specifies an optional `as reference` part - what does that part do?
-// most likely `as reference` will refer to another type that was already defined in its dedicated
-// join statement.
-
-/**
- * A {@code KeepReferenceExpression} retains links to other instances in the original models. All
- * objects that are referenced in the base models will also be available in the resulting ModelJoin
- * views.
- * <p>
- * As references are directional, each expression also distinguishes between {@code outgoing} and
- * {@code incoming} references - depending on whether the model class of {@code this} expression
- * owns the reference ({@code outgoing}) or instances of this model class are being referenced
- * ({@code incoming}).
- * <p>
- * The referenced instances will be made available according to a number of keep statements which
- * specify the attributes to include. This boils down to the creation of a nested ModelJoin view for
- * these instances.
- *
- * @author Rico Bergmann
- */
-public class KeepReferenceExpression extends CompoundKeepExpression {
-
-  /**
-   * The {@code ReferenceDirection} defines whether a reference is owned by the containing model
-   * class or whether it is the class being referenced.
-   */
-  public enum ReferenceDirection {
-
-    /**
-     * Indicates that the containing model class owns the reference.
-     */
-    OUTGOING,
-
-    /**
-     * Indicates that the containing model class is referenced by some other class.
-     */
-    INCOMING
-  }
-
-  /**
-   * The {@code KeepReferenceBuilder} enables the construction of new {@code
-   * KeepReferenceExpression} instances through a nice and fluent interface.
-   *
-   * @author Rico Bergmann
-   */
-  public static class KeepReferenceBuilder {
-
-    private ReferenceDirection referenceDirection;
-    private AttributePath attribute;
-    private ClassResource target;
-
-    @Nonnull
-    private List<KeepExpression> keeps;
-
-    /**
-     * Default constructor.
-     */
-    private KeepReferenceBuilder() {
-      this.keeps = new ArrayList<>();
-    }
-
-    /**
-     * Creates an outgoing reference for the given attribute.
-     */
-    @Nonnull
-    public KeepReferenceBuilder outgoing(@Nonnull AttributePath attribute) {
-      this.referenceDirection = ReferenceDirection.OUTGOING;
-      this.attribute = attribute;
-      return this;
-    }
-
-    /**
-     * Creates an incoming reference for the given attribute.
-     */
-    @Nonnull
-    public KeepReferenceBuilder incoming(@Nonnull AttributePath attribute) {
-      this.referenceDirection = ReferenceDirection.INCOMING;
-      this.attribute = attribute;
-      return this;
-    }
-
-    /**
-     * Specifies the name of the attribute in the target join.
-     */
-    @Nonnull
-    public KeepReferenceBuilder as(@Nonnull ClassResource target) {
-      this.target = target;
-      return this;
-    }
-
-    /**
-     * Adds an attribute to the view for the referenced instances.
-     */
-    @Nonnull
-    public KeepReferenceBuilder keep(@Nonnull KeepExpression keepExpression) {
-      this.keeps.add(keepExpression);
-      return this;
-    }
-
-    /**
-     * Finishes the construction process.
-     */
-    @Nonnull
-    public KeepReferenceExpression buildExpression() {
-      Assert.noNullArguments("All components must be specified", attribute, referenceDirection, target, keeps);
-      return new KeepReferenceExpression(attribute, referenceDirection, target, keeps);
-    }
-  }
-
-  /**
-   * Starts the creation process for a new {@code KeepReferenceExpression}.
-   */
-  @Nonnull
-  public static KeepReferenceBuilder keep() {
-    return new KeepReferenceBuilder();
-  }
-
-  @Nonnull
-  private final AttributePath attribute;
-
-  @Nonnull
-  private final ReferenceDirection referenceDirection;
-
-  @Nonnull
-  private final ClassResource target;
-
-  @Nonnull
-  private final List<KeepExpression> keeps;
-
-  /**
-   * Full constructor.
-   *
-   * @param attribute the attribute of the source model which contains the references
-   * @param referenceDirection whether the source model owns the reference or is being
-   *     referenced
-   * @param target the name of the class which enca
-   * @param keeps the statements which should be build the "nested" view for the references
-   */
-  public KeepReferenceExpression(
-      @Nonnull AttributePath attribute,
-      @Nonnull ReferenceDirection referenceDirection,
-      @Nonnull ClassResource target,
-      @Nonnull List<KeepExpression> keeps) {
-    this.attribute = attribute;
-    this.referenceDirection = referenceDirection;
-    this.target = target;
-    this.keeps = keeps;
-  }
-
-  /**
-   * Provides the attribute of the source model which contains the references.
-   */
-  @Nonnull
-  public AttributePath getAttribute() {
-    return attribute;
-  }
-
-  /**
-   * Provides the kind of reference, that is whether the containing Join owns the reference or is
-   * being referenced by another model class or Join.
-   */
-  @Nonnull
-  public ReferenceDirection getReferenceDirection() {
-    return referenceDirection;
-  }
-
-  /**
-   * Provides the name of the attribute under which the referenced instances should be made
-   * available.
-   */
-  @Nonnull
-  public ClassResource getTarget() {
-    return target;
-  }
-
-  /**
-   * Provides all {@code KeepExpression keep expressions} that should be used to build the Join for
-   * the referenced instances.
-   */
-  @Nonnull
-  @Override
-  public List<KeepExpression> getKeeps() {
-    return new ArrayList<>(keeps);
-  }
-
-  @Override
-  public void accept(@Nonnull KeepExpressionVisitor visitor) {
-    visitor.visit(this);
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-    KeepReferenceExpression that = (KeepReferenceExpression) o;
-    return attribute.equals(that.attribute) && target.equals(that.target);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(attribute, target);
-  }
-
-  @Override
-  public String toString() {
-    String directionString = referenceDirection.toString().toLowerCase();
-    return "keep " + directionString + " " + attribute + " as type " + target;
-  }
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepSubTypeExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepSubTypeExpression.java
deleted file mode 100644
index 76e8d6027462a00d341906020ca57c638b1ed074..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepSubTypeExpression.java
+++ /dev/null
@@ -1,167 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.grammar;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import javax.annotation.Nonnull;
-import org.rosi_project.model_sync.model_join.representation.core.ClassResource;
-import org.rosi_project.model_sync.model_join.representation.util.Assert;
-
-/**
- * A {@code KeepSubTypeExpression} instructs the {@code ModelJoin} runtime to instantiate the most
- * specific type that inherits from this type as well. The additional instance will be built
- * according to the {@code KeepExpression keep statements} that it is constructed of.
- * <p>
- * In order to prevent ambiguities a {@code KeepSubTypeExpression} may only be specified on joins
- * that do not participate in another {@link JoinExpression join statement}.
- *
- * @author Rico Bergmann
- */
-public class KeepSubTypeExpression extends CompoundKeepExpression {
-
-  /**
-   * The {@code KeepSubTypeBuilder} enables the construction of new {@code KeepSubTypeExpression}
-   * instances through a nice and fluent interface.
-   *
-   * @author Rico Bergmann
-   */
-  public static class KeepSubTypeBuilder {
-
-    private ClassResource typeToKeep;
-    private ClassResource target;
-    private List<KeepExpression> keeps;
-
-    /**
-     * Default constructor.
-     */
-    private KeepSubTypeBuilder() {
-      this.keeps = new ArrayList<>();
-    }
-
-    /**
-     * Specifies the subtype that should be instantiated.
-     */
-    @Nonnull
-    public KeepSubTypeBuilder subtype(@Nonnull ClassResource type) {
-      this.typeToKeep = type;
-      return this;
-    }
-
-    /**
-     * Specifies the name of the class that should be generated for the subtype instances.
-     */
-    @Nonnull
-    public KeepSubTypeBuilder as(@Nonnull ClassResource target) {
-      this.target = target;
-      return this;
-    }
-
-    /**
-     * Adds a {@link KeepExpression keep statement} for the subtype-class. The described attribute
-     * will be initialized for each instantiated subtype element.
-     */
-    @Nonnull
-    public KeepSubTypeBuilder keep(@Nonnull KeepExpression keep) {
-      this.keeps.add(keep);
-      return this;
-    }
-
-    /**
-     * Finishes the construction process.
-     */
-    @Nonnull
-    public KeepSubTypeExpression buildExpression() {
-      Assert.noNullArguments("All components must be specified", typeToKeep, target, keeps);
-      return new KeepSubTypeExpression(typeToKeep, target, keeps);
-    }
-
-  }
-
-  /**
-   * Starts the creation process for a new {@code KeepSubTypeExpression}.
-   */
-  @Nonnull
-  public static KeepSubTypeBuilder keep() {
-    return new KeepSubTypeBuilder();
-  }
-
-  @Nonnull
-  private final ClassResource typeToKeep;
-
-  @Nonnull
-  private final ClassResource target;
-
-  @Nonnull
-  private final List<KeepExpression> keeps;
-
-  /**
-   * Full constructor.
-   *
-   * @param typeToKeep the subtype that should be instantiated.
-   * @param target the name of the view that should be generated for all matching instances
-   * @param keeps the keep statements that should form the attributes of the generated view
-   *     instances
-   */
-  public KeepSubTypeExpression(
-      @Nonnull ClassResource typeToKeep,
-      @Nonnull ClassResource target,
-      @Nonnull List<KeepExpression> keeps) {
-    this.typeToKeep = typeToKeep;
-    this.target = target;
-    this.keeps = keeps;
-  }
-
-  /**
-   * Provides the subtype that should be instantiated.
-   */
-  @Nonnull
-  public ClassResource getType() {
-    return typeToKeep;
-  }
-
-  /**
-   * Provides the name of the view that should be generated for all matching instances.
-   */
-  @Nonnull
-  public ClassResource getTarget() {
-    return target;
-  }
-
-  /**
-   * Provides all {@code KeepExpression keep expressions} that should be used to build the Join for
-   * the instances of the subclass instances.
-   */
-  @Nonnull
-  @Override
-  public List<KeepExpression> getKeeps() {
-    return new ArrayList<>(keeps);
-  }
-
-  @Override
-  public void accept(@Nonnull KeepExpressionVisitor visitor) {
-    visitor.visit(this);
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-    KeepSubTypeExpression that = (KeepSubTypeExpression) o;
-    return typeToKeep.equals(that.typeToKeep) &&
-        target.equals(that.target);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(typeToKeep, target);
-  }
-
-  @Override
-  public String toString() {
-    return "keep subtype " + typeToKeep + " as " + target;
-  }
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepSuperTypeExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepSuperTypeExpression.java
deleted file mode 100644
index 6c72a3d9a42fdef32eafe621ceba232af271b803..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepSuperTypeExpression.java
+++ /dev/null
@@ -1,166 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.grammar;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import javax.annotation.Nonnull;
-import org.rosi_project.model_sync.model_join.representation.core.ClassResource;
-import org.rosi_project.model_sync.model_join.representation.util.Assert;
-
-// TODO add doc
-
-/**
- * A {@code KeepSuperTypeExpression} instructs the {@code ModelJoin} runtime to instantiate the a
- * supertype of some class in a join along an instance of that class. The additional instance will
- * be built according to the {@code KeepExpression keep statements} that it is constructed of.
- *
- * @author Rico Bergmann
- */
-public class KeepSuperTypeExpression extends CompoundKeepExpression {
-
-  /**
-   * The {@code KeepSuperTypeBuilder} enables the construction of new {@code KeepSuperTypeExpression}
-   * instances through a nice and fluent interface.
-   *
-   * @author Rico Bergmann
-   */
-  public static class KeepSuperTypeBuilder {
-
-    private ClassResource typeToKeep;
-    private ClassResource target;
-    private List<KeepExpression> keeps;
-
-    /**
-     * Default constructor.
-     */
-    private KeepSuperTypeBuilder() {
-      this.keeps = new ArrayList<>();
-    }
-
-    /**
-     * Specifies the supertype that should be instantiated.
-     */
-    @Nonnull
-    public KeepSuperTypeBuilder supertype(@Nonnull ClassResource type) {
-      this.typeToKeep = type;
-      return this;
-    }
-
-    /**
-     * Specifies the name of the class that should be generated for the subtype instances.
-     */
-    @Nonnull
-    public KeepSuperTypeBuilder as(@Nonnull ClassResource target) {
-      this.target = target;
-      return this;
-    }
-
-    /**
-     * Adds a {@link KeepExpression keep statement} for the subtype-class. The described attribute
-     * will be initialized for each instantiated subtype element.
-     */
-    @Nonnull
-    public KeepSuperTypeBuilder keep(@Nonnull KeepExpression keep) {
-      this.keeps.add(keep);
-      return this;
-    }
-
-    /**
-     * Finishes the construction process.
-     */
-    @Nonnull
-    public KeepSuperTypeExpression buildExpression() {
-      Assert.noNullArguments("All components must be specified", typeToKeep, target, keeps);
-      return new KeepSuperTypeExpression(typeToKeep, target, keeps);
-    }
-
-  }
-
-  /**
-   * Starts the creation process for a new {@code KeepSuperTypeExpression}.
-   */
-  @Nonnull
-  public static KeepSuperTypeBuilder keep() {
-    return new KeepSuperTypeBuilder();
-  }
-
-  @Nonnull
-  private final ClassResource typeToKeep;
-
-  @Nonnull
-  private final ClassResource target;
-
-  @Nonnull
-  private final List<KeepExpression> keeps;
-
-  /**
-   * Full constructor.
-   *
-   * @param typeToKeep the supertype that should be instantiated.
-   * @param target the name of the view that should be generated for all matching instances
-   * @param keeps the keep statements that should form the attributes of the generated view
-   *     instances
-   */
-  public KeepSuperTypeExpression(
-      @Nonnull ClassResource typeToKeep,
-      @Nonnull ClassResource target,
-      @Nonnull List<KeepExpression> keeps) {
-    this.typeToKeep = typeToKeep;
-    this.target = target;
-    this.keeps = keeps;
-  }
-
-  /**
-   * Provides the supertype that should be instantiated.
-   */
-  @Nonnull
-  public ClassResource getType() {
-    return typeToKeep;
-  }
-
-  /**
-   * Provides the name of the view that should be generated for all matching instances.
-   */
-  @Nonnull
-  public ClassResource getTarget() {
-    return target;
-  }
-
-  /**
-   * Provides all {@code KeepExpression keep expressions} that should be used to build the Join for
-   * the instances of the superclass instances.
-   */
-  @Nonnull
-  @Override
-  public List<KeepExpression> getKeeps() {
-    return new ArrayList<>(keeps);
-  }
-
-  @Override
-  public void accept(@Nonnull KeepExpressionVisitor visitor) {
-    visitor.visit(this);
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-    KeepSuperTypeExpression that = (KeepSuperTypeExpression) o;
-    return typeToKeep.equals(that.typeToKeep) &&
-        target.equals(that.target);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(typeToKeep, target);
-  }
-
-  @Override
-  public String toString() {
-    return "keep supertype " + typeToKeep + " as " + target;
-  }
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/ModelJoinExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/ModelJoinExpression.java
deleted file mode 100644
index 30382b532ada48b163756519650e01c25516fc3a..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/ModelJoinExpression.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.grammar;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Objects;
-import javax.annotation.Nonnull;
-
-/**
- * The {@code ModelJoinExpression} represents an actual ModelJoin, i.e. a specification of which
- * joins to use and how they should be built.
- *
- * @author Rico Bergmann
- */
-public class ModelJoinExpression implements Iterable<JoinExpression> {
-	
-  private String name = "";
-  
-  public String getName() {
-	  return name;
-  }
-  
-  public void setName(String n) {
-	  name = n;
-  }
-
-  /**
-   * Creates a new {@code ModelJoin}.
-   *
-   * @param joins the joins that should be included.
-   */
-  @Nonnull
-  public static ModelJoinExpression with(@Nonnull List<JoinExpression> joins) {
-    return new ModelJoinExpression(joins);
-  }
-
-  /**
-   * Ensures that all joins specify distinct join targets and throws an {@code
-   * IllegalArgumentException} otherwise.
-   */
-  private static void assertDifferentTargetsForAllJoins(Collection<JoinExpression> joinsToCheck) {
-    final long totalNumberOfJoins = joinsToCheck.size();
-    final long numberOfDistinctTargetsSpecified = joinsToCheck.stream()//
-        .map(JoinExpression::getTarget) //
-        .distinct() //
-        .count();
-
-    if (numberOfDistinctTargetsSpecified < totalNumberOfJoins) {
-      throw new IllegalArgumentException("Some joins share the same target");
-    }
-  }
-
-  @Nonnull
-  private final List<JoinExpression> joins;
-
-  /**
-   * Full constructor.
-   *
-   * @param joins the joins that this ModelJoin consists of
-   */
-  public ModelJoinExpression(List<JoinExpression> joins) {
-    assertDifferentTargetsForAllJoins(joins);
-    this.joins = joins;
-  }
-
-  /**
-   * Provides all joins {@code this} model specifies.
-   */
-  @Nonnull
-  public Collection<JoinExpression> getJoins() {
-    return new ArrayList<>(joins);
-  }
-
-  @Nonnull
-  @Override
-  public Iterator<JoinExpression> iterator() {
-    return joins.iterator();
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-    ModelJoinExpression that = (ModelJoinExpression) o;
-    return joins.equals(that.joins);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(joins);
-  }
-
-  @Override
-  public String toString() {
-    return joins.toString();
-  }
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/NaturalJoinExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/NaturalJoinExpression.java
deleted file mode 100644
index 7c3d7b4d9aa8a374d367bf5d3ba6948531538b9c..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/NaturalJoinExpression.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.grammar;
-
-import java.util.List;
-import javax.annotation.Nonnull;
-import org.rosi_project.model_sync.model_join.representation.core.ClassResource;
-
-/**
- * The {@code natural join} combines model classes based on attributes of the
- * same name and type.
- * <p>
- * As an example, consider the following two classes:
- * 
- * <pre>
- * {
- * 	&#64;code
- * 	class Person {
- * 		String firstname;
- * 		String lastname;
- * 		Date dateOfBirth;
- * 		Char gender;
- * 		// ... other code omitted
- * 	}
- *
- * 	class Employee {
- * 		int id;
- * 		String firstname;
- * 		String lastname;
- * 		Date dateOfBirth;
- * 		int salary;
- * 		// ... other code omitted
- * 	}
- * }
- * </pre>
- * <p>
- * Performing a natural join on {@code Person} and {@code Employee} will combine
- * instances only if they share the same first name, last name and date of
- * birth. All other fields will not be considered during the comparison.
- * 
- * <pre>
- * ┌───────────────────┐             ┌───────────────────┐
- * │ Person            │             │ Employee          │
- * ├───────────────────┤             ├───────────────────┤
- * │firstname: String  │ ┄┄┄┄┄┄┄╮    │id: int            │
- * │lastname: String   │ ┄┄┄┄┄╮ ╰┄┄┄ │firstname: String  │
- * │dateOfBirth: Date  │ ┄┄┄╮ ╰┄┄┄┄┄ │lastname: String   │
- * │gender: Char       │    ╰┄┄┄┄┄┄┄ │dateOfBirth: Date  │
- * ├───────────────────┤             │salary: int        │
- * │ ...               │             ├───────────────────┤
- * └───────────────────┘             │ ...               │
- *                                   └───────────────────┘
- * </pre>
- * <p>
- * The resulting class will by default only contain the attributes that where
- * used in comparison (first name, last name and date of birth in the example).
- *
- * @author Rico Bergmann
- */
-public class NaturalJoinExpression extends JoinExpression {
-
-	/*
-	 * TODO: discuss should the natural join extend theta join instead (from a
-	 * theoretical view more appropriate. However this would also mean that the
-	 * natural join has to derive the join condition as well. This in turn would
-	 * also meant that class resources would have to know which attributes are
-	 * defined on them.
-	 */
-
-	/**
-	 * Full constructor.
-	 *
-	 * @param left
-	 *            the left class to use in the join
-	 * @param right
-	 *            the right class to use in the join
-	 * @param target
-	 *            the name of the resulting view
-	 * @param keeps
-	 *            the keep statements in the join
-	 */
-	public NaturalJoinExpression(@Nonnull ClassResource left, @Nonnull ClassResource right,
-			@Nonnull ClassResource target, @Nonnull List<KeepExpression> keeps) {
-		super(left, right, target, keeps);
-	}
-
-	@Nonnull
-	@Override
-	public JoinType getType() {
-		return JoinType.NATURAL;
-	}
-
-	@Nonnull
-	@Override
-	String getJoinTypeAsString() {
-		return "natural join";
-	}
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/OuterJoinExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/OuterJoinExpression.java
deleted file mode 100644
index 376dad0da9717dea91041d9951f1febe2e0de01c..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/OuterJoinExpression.java
+++ /dev/null
@@ -1,150 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.grammar;
-
-import java.util.List;
-import javax.annotation.Nonnull;
-import org.rosi_project.model_sync.model_join.representation.core.ClassResource;
-
-/**
- * The {@code outer join} is a special kind of {@code natural join}: depending
- * on its specific type, all elements of one source will definitely be included
- * - potentially being joined with matching instances of the other source.
- * <p>
- * Matches will be determined the same way as with a normal
- * {@code natural join}. However, depending on the kind of join, the result will
- * include all instances of the {@code left} or {@code right} source model, no
- * matter whether they have a matching instance in the other model or not. In
- * case that some instance has no corresponding instance in the other model, all
- * fields that belong to the other model will be set to {@code null}.
- * <p>
- * Consider the following example (derived from the model shown in the
- * {@link NaturalJoinExpression} documentation)
- * 
- * <pre>
- * Person:
- * ┌───────────┬──────────┬─────────────┬────────┐
- * │ firstname │ lastname │ dateOfBirth │ gender │
- * ├───────────┼──────────┼─────────────┼────────┤
- * │ Jane      │ Doe      │ 1999-01-01  │   f    │
- * │ John      │ Doe      │ 1998-02-03  │   m    │
- * │ Maria     │ Miller   │ 1990-12-31  │   f    │
- * └───────────┴──────────┴─────────────┴────────┘
- *
- * Employee:
- * ┌────┬───────────┬──────────┬─────────────┬────────┐
- * │ id │ firstname │ lastname │ dateOfBirth │ salary │
- * ├────┼───────────┼──────────┼─────────────┼────────┤
- * │ 1  │ Jane      │ Doe      │ 1999-01-01  │ 20000  │
- * │ 2  │ John      │ Doe      │ 1997-03-04  │ 15000  │
- * │ 3  │ Maria     │ Miller   │ 1990-12-31  │ 17500  │
- * └────┴───────────┴──────────┴─────────────┴────────┘
- * </pre>
- * 
- * Performing an left outer join as described in the
- * {@link NaturalJoinExpression natural join} documentation will lead to the
- * following result (again written in relational style):
- * 
- * <pre>
- * ┌───────────┬──────────┬─────────────┬────────┬──────┬────────┐
- * │ firstname │ lastname │ dateOfBirth │ gender │ id   │ salary │
- * ├───────────┼──────────┼─────────────┼────────┼──────┼────────┤
- * │ Jane      │ Doe      │ 1999-01-01  │   f    │ 1    │ 20000  │
- * │ John      │ Doe      │ 1998-02-03  │   m    │ NULL │ NULL   │
- * │ Maria     │ Miller   │ 1990-12-31  │   f    │ 3    │ 17500  │
- * └───────────┴──────────┴─────────────┴────────┴──────┴────────┘
- * </pre>
- *
- * @author Rico Bergmann
- */
-public class OuterJoinExpression extends NaturalJoinExpression {
-
-	/**
-	 * The {@code JoinDirection} denotes which side of the source models should
-	 * keep all of its instances - no matter whether they have a matching
-	 * instances in the other model or not.
-	 */
-	public enum JoinDirection {
-		LEFT, RIGHT
-	}
-
-	@Nonnull
-	private final JoinDirection direction;
-
-	/**
-	 * Full constructor.
-	 *
-	 * @param left
-	 *            the left class to use in the join
-	 * @param right
-	 *            the right class to use in the join
-	 * @param target
-	 *            the name of the resulting view
-	 * @param direction
-	 *            the source model which should definitely be kept
-	 * @param keeps
-	 *            the keep statements in the join
-	 */
-	public OuterJoinExpression(@Nonnull ClassResource left, @Nonnull ClassResource right, @Nonnull ClassResource target,
-			@Nonnull JoinDirection direction, @Nonnull List<KeepExpression> keeps) {
-		super(left, right, target, keeps);
-		this.direction = direction;
-	}
-
-	/**
-	 * Provides the position of the source model on which the join should be
-	 * based.
-	 */
-	@Nonnull
-	public JoinDirection getDirection() {
-		return direction;
-	}
-
-	/**
-	 * Provides the source model on which the join should be based.
-	 */
-	@Override
-	public ClassResource getBaseModel() {
-		switch (direction) {
-		case LEFT:
-			return left;
-		case RIGHT:
-			return right;
-		default:
-			throw new AssertionError(direction);
-		}
-	}
-
-	@Override
-	public ClassResource getOtherModel() {
-		switch (direction) {
-		case LEFT:
-			return right;
-		case RIGHT:
-			return left;
-		default:
-			throw new AssertionError(direction);
-		}
-	}
-
-	@Nonnull
-	@Override
-	public JoinType getType() {
-		return JoinType.OUTER;
-	}
-
-	@Nonnull
-	@Override
-	String getJoinTypeAsString() {
-		String directionString;
-		switch (this.direction) {
-		case LEFT:
-			directionString = "left";
-			break;
-		case RIGHT:
-			directionString = "right";
-			break;
-		default:
-			throw new AssertionError(this.direction);
-		}
-		return directionString + " outer join";
-	}
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/ThetaJoinExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/ThetaJoinExpression.java
deleted file mode 100644
index 39f777b05b511d0248c0c84a47535c05470dc892..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/ThetaJoinExpression.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.grammar;
-
-import java.util.List;
-import javax.annotation.Nonnull;
-import org.rosi_project.model_sync.model_join.representation.core.ClassResource;
-import org.rosi_project.model_sync.model_join.representation.core.OCLConstraint;
-
-/**
- * A {@code theta join} is the most general type of join. It will determine join-compatibility
- * based on an arbitrary predicate which may evaluate to {@code true} or {@code false}, denoting
- * whether two instances are to be joined or not.
- * <p>
- * To specify this condition, {@link OCLConstraint OCL} is used.
- * <p>
- * As a simple example, consider the following two classes:
- * <pre>
- * ┌───────────────────┐     ┌───────────────────┐
- * │ Person            │     │ Employee          │
- * ├───────────────────┤     ├───────────────────┤
- * │firstname: String  │     │id: int            │
- * │lastname: String   │     │fullname: String   │
- * │dateOfBirth: Date  │     │dateOfBirth: Date  │
- * │gender: Char       │     │salary: int        │
- * ├───────────────────┤     ├───────────────────┤
- * │ ...               │     │ ...               │
- * └───────────────────┘     └───────────────────┘
- * </pre>
- * <p>
- * The expression {@code person.firstname + ' ' + person.lastname = employee.fullname} would than
- * match all persons with employee instances if they have the same name.
- *
- * @author Rico Bergmann
- */
-public class ThetaJoinExpression extends JoinExpression {
-
-  @Nonnull
-  private final OCLConstraint condition;
-
-  /**
-   * Full constructor.
-   *
-   * @param left the left class to use in the join
-   * @param right the right class to use in the join
-   * @param target the name of the resulting view
-   * @param condition the condition which should be used to determine join-compatibility
-   */
-  public ThetaJoinExpression(
-      @Nonnull ClassResource left,
-      @Nonnull ClassResource right,
-      @Nonnull ClassResource target,
-      @Nonnull OCLConstraint condition,
-      @Nonnull List<KeepExpression> keeps) {
-    super(left, right, target, keeps);
-    this.condition = condition;
-  }
-
-  /**
-   * Provides the condition which should be used to determine whether two instances are join
-   * compatible or not.
-   */
-  @Nonnull
-  public OCLConstraint getCondition() {
-    return condition;
-  }
-
-  @Nonnull
-  @Override
-  public JoinType getType() {
-    return JoinType.THETA;
-  }
-
-  @Nonnull
-  @Override
-  String getJoinTypeAsString() {
-    return "theta join";
-  }
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/ModelJoinParser.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/ModelJoinParser.java
deleted file mode 100644
index 87c6f0cc6383feb4e067c767e08bd12c303d308e..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/ModelJoinParser.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.parser;
-
-import java.io.File;
-import java.util.Optional;
-import javax.annotation.Nonnull;
-import org.rosi_project.model_sync.model_join.representation.grammar.ModelJoinExpression;
-
-/**
- * The {@code ModelJoinParser} reads a {@code ModelJoin} file from disk and creates a matching
- * logical representation for it.
- *
- * @author Rico Bergmann
- */
-public interface ModelJoinParser {
-
-  /**
-   * Converts the {@code ModelJoin} file into a {@link ModelJoinExpression}, wrapped into an {@code
-   * Optional}. If parsing fails, an empty {@code Optional} will be returned.
-   */
-  @Nonnull
-  Optional<ModelJoinExpression> read(@Nonnull File modelFile);
-
-  /**
-   * Converts the {@code ModelJoin} file into a {@link ModelJoinExpression}. If parsing fails, a
-   * {@link ModelJoinParsingException} will be thrown.
-   *
-   * @throws ModelJoinParsingException if the model may not be parsed for some reason.
-   */
-  @Nonnull
-  ModelJoinExpression readOrThrow(@Nonnull File modelFile);
-
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/ModelJoinParsingException.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/ModelJoinParsingException.java
deleted file mode 100644
index 6b72c01ee5d4926b87db1cfa80bc9839e385d104..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/ModelJoinParsingException.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.parser;
-
-/**
- * The {@code ModelJoinParsingException} indicates that a {@code ModelJoin} file could not be read
- * correctly, e.g. because of missing values or a malformed structure.
- *
- * @author Rico Bergmann
- */
-public class ModelJoinParsingException extends RuntimeException {
-
-  /**
-   * @see RuntimeException#RuntimeException(String)
-   */
-  public ModelJoinParsingException(String message) {
-    super(message);
-  }
-
-  /**
-   * @see RuntimeException#RuntimeException(String, Throwable)
-   */
-  public ModelJoinParsingException(String message, Throwable cause) {
-    super(message, cause);
-  }
-
-  /**
-   * @see RuntimeException#RuntimeException(Throwable)
-   */
-  public ModelJoinParsingException(Throwable cause) {
-    super(cause);
-  }
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/AntlrBackedModelJoinParser.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/AntlrBackedModelJoinParser.java
deleted file mode 100644
index 86773781a112c27a910fca63acc710f9d50f331f..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/AntlrBackedModelJoinParser.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.parser.antlr;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Optional;
-import javax.annotation.Nonnull;
-import org.antlr.v4.runtime.CharStream;
-import org.antlr.v4.runtime.CharStreams;
-import org.antlr.v4.runtime.CommonTokenStream;
-import org.antlr.v4.runtime.TokenStream;
-import org.rosi_project.model_sync.model_join.representation.grammar.ModelJoinExpression;
-import org.rosi_project.model_sync.model_join.representation.parser.ModelJoinParser;
-import org.rosi_project.model_sync.model_join.representation.parser.ModelJoinParsingException;
-import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinLexer;
-
-/**
- * The {@code AntlrBackedModelJoinParser} reads a {@code ModelJoin} file according to a compiled
- * {@code ANTLR} grammar and generates the matching {@link ModelJoinExpression} for the file.
- *
- * @author Rico Bergmann
- * @see <a href="https://www.antlr.org/">ANTLR project</a>
- */
-public class AntlrBackedModelJoinParser implements ModelJoinParser {
-
-  @Nonnull
-  @Override
-  public Optional<ModelJoinExpression> read(@Nonnull File modelFile) {
-    try {
-      return Optional.of(invokeAntlr(modelFile));
-    } catch (ModelJoinParsingException e) {
-      return Optional.empty();
-    }
-  }
-
-  @Nonnull
-  @Override
-  public ModelJoinExpression readOrThrow(@Nonnull File modelFile) {
-    return invokeAntlr(modelFile);
-  }
-
-  /**
-   * Executes the whole ANTLR workflow.
-   *
-   * @throws ModelJoinParsingException if the workflow fails. Details on the error will be added
-   *     to the exception.
-   */
-  protected ModelJoinExpression invokeAntlr(@Nonnull File modelFile) {
-    CharStream modelStream = consumeCompleteModelFileContent(modelFile);
-    ModelJoinLexer lexer = initializeLexerBasedOn(modelStream);
-    TokenStream tokenStream = tokenize(lexer);
-
-    org.rosi_project.model_sync.model_join.representation.parser.antlr.generated. //
-        ModelJoinParser modelJoinParser = initializeParserBasedOn(tokenStream);
-
-    org.rosi_project.model_sync.model_join.representation.parser.antlr.generated. //
-        ModelJoinParser.ModeljoinContext modelJoinContext = modelJoinParser.modeljoin();
-
-    ModelJoinVisitor modelJoinVisitor = new ModelJoinVisitor();
-
-    return modelJoinVisitor.visitModeljoin(modelJoinContext);
-  }
-
-  /**
-   * Converts the content of a {@code ModelJoin} file into an ANTLR input stream.
-   *
-   * @throws ModelJoinParsingException if the file may not be read
-   */
-  @Nonnull
-  protected CharStream consumeCompleteModelFileContent(@Nonnull File modelFile) {
-    try {
-      return CharStreams.fromPath(modelFile.toPath());
-    } catch (IOException e) {
-      throw new ModelJoinParsingException(e);
-    }
-  }
-
-  /**
-   * Sets up a lexer for the given {@code ModelJoin} file.
-   */
-  @Nonnull
-  protected ModelJoinLexer initializeLexerBasedOn(@Nonnull CharStream modelFile) {
-    return new ModelJoinLexer(modelFile);
-  }
-
-  /**
-   * Executes the lexing step.
-   */
-  @Nonnull
-  protected TokenStream tokenize(@Nonnull ModelJoinLexer lexer) {
-    return new CommonTokenStream(lexer);
-  }
-
-  /**
-   * Sets up the parser.
-   */
-  @Nonnull
-  protected org.rosi_project.model_sync.model_join.representation.parser.antlr.generated. //
-      ModelJoinParser initializeParserBasedOn(@Nonnull TokenStream tokens) {
-    return new org.rosi_project.model_sync.model_join.representation.parser.antlr.generated. //
-        ModelJoinParser(tokens);
-  }
-
-}
-
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/JoinStatementVisitor.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/JoinStatementVisitor.java
deleted file mode 100644
index 3fe1c7bd180e24161204ccab4a59d2a557985536..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/JoinStatementVisitor.java
+++ /dev/null
@@ -1,183 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.parser.antlr;
-
-import javax.annotation.Nonnull;
-import org.rosi_project.model_sync.model_join.representation.core.ClassResource;
-import org.rosi_project.model_sync.model_join.representation.core.OCLConstraint;
-import org.rosi_project.model_sync.model_join.representation.grammar.JoinExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.JoinExpression.JoinType;
-import org.rosi_project.model_sync.model_join.representation.grammar.NaturalJoinExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.OuterJoinExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.ThetaJoinExpression;
-import org.rosi_project.model_sync.model_join.representation.parser.ModelJoinParsingException;
-import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinBaseVisitor;
-import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.JoinContext;
-import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.NaturaljoinContext;
-import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.OuterjoinContext;
-import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.ThetajoinContext;
-import org.rosi_project.model_sync.model_join.representation.util.JoinFactory;
-import org.rosi_project.model_sync.model_join.representation.util.JoinFactory.NaturalJoinBuilder;
-import org.rosi_project.model_sync.model_join.representation.util.JoinFactory.OuterJoinBuilder;
-import org.rosi_project.model_sync.model_join.representation.util.JoinFactory.ThetaJoinBuilder;
-
-/**
- * The {@code JoinStatementVisitor} creates {@link JoinExpression} instances for a parsed {@code
- * ModelJoin} file.
- *
- * @author Rico Bergmann
- */
-public class JoinStatementVisitor extends ModelJoinBaseVisitor<JoinExpression> {
-
-  private final KeepStatementVisitor keepStatementVisitor;
-
-  /**
-   * Default constructor. Nothing special about it.
-   */
-  JoinStatementVisitor() {
-    this.keepStatementVisitor = new KeepStatementVisitor();
-  }
-
-  @Override
-  public JoinExpression visitJoin(JoinContext ctx) {
-    JoinType joinType = determineJoinType(ctx);
-    return invokeJoinBuilderAccordingTo(joinType, ctx);
-  }
-
-  /**
-   * Checks, which kind of join is specified in a specific {@code JoinContext}.
-   */
-  private JoinType determineJoinType(@Nonnull JoinContext ctx) {
-    if (ctx.thetajoin() != null) {
-      return JoinType.THETA;
-    } else if (ctx.naturaljoin() != null) {
-      return JoinType.NATURAL;
-    } else if (ctx.outerjoin() != null) {
-      return JoinType.OUTER;
-    } else {
-      throw new ModelJoinParsingException("Unkown join type in join " + ctx);
-    }
-  }
-
-  /**
-   * Generates a {@link JoinExpression} according to the {@link JoinType} of the given {@code
-   * JoinContext}.
-   */
-  private JoinExpression invokeJoinBuilderAccordingTo(@Nonnull JoinType type,
-      @Nonnull JoinContext ctx) {
-    switch (type) {
-      case THETA:
-        return generateThetaJoin(ctx);
-      case NATURAL:
-        return generateNaturalJoin(ctx);
-      case OUTER:
-        return generateOuterJoin(ctx);
-      default:
-        throw new AssertionError(type);
-    }
-  }
-
-  /**
-   * Creates the {@link ThetaJoinExpression} instance contained in a {@code JoinContext}. This
-   * method assumes that the provided {@code ctx} indeed contains a theta join.
-   */
-  private ThetaJoinExpression generateThetaJoin(@Nonnull JoinContext ctx) {
-    ThetajoinContext thetajoinContext = ctx.thetajoin();
-
-    ClassResource left = ClassResource.fromQualifiedName(thetajoinContext.classres(0).getText());
-    ClassResource right = ClassResource.fromQualifiedName(thetajoinContext.classres(1).getText());
-
-    ThetaJoinBuilder joinBuilder = JoinFactory.createNew()
-        .theta()
-        .join(left)
-        .with(right)
-        .as(ClassResource.fromQualifiedName(ctx.classres().getText()))
-        .where(OCLConstraint.of(thetajoinContext.oclcond().getText()));
-
-    ctx.keepaggregatesexpr().stream()
-        .map(keepStatementVisitor::visitKeepaggregatesexpr)
-        .forEach(joinBuilder::keep);
-    ctx.keepattributesexpr().stream()
-        .map(keepStatementVisitor::visitKeepattributesexpr)
-        .forEach(joinBuilder::keep);
-    ctx.keepcalculatedexpr().stream()
-        .map(keepStatementVisitor::visitKeepcalculatedexpr)
-        .forEach(joinBuilder::keep);
-    ctx.keepexpr().stream()
-        .map(keepStatementVisitor::visitKeepexpr)
-        .forEach(joinBuilder::keep);
-
-    return joinBuilder.done();
-  }
-
-  /**
-   * Creates the {@link NaturalJoinExpression} instance contained in a {@code JoinContext}. This
-   * method assumes that the provided {@code ctx} indeed contains a natural join.
-   */
-  private NaturalJoinExpression generateNaturalJoin(@Nonnull JoinContext ctx) {
-    NaturaljoinContext naturalJoinContext = ctx.naturaljoin();
-
-    ClassResource left = ClassResource.fromQualifiedName(naturalJoinContext.classres(0).getText());
-    ClassResource right = ClassResource.fromQualifiedName(naturalJoinContext.classres(1).getText());
-
-    NaturalJoinBuilder joinBuilder = JoinFactory.createNew()
-        .natural()
-        .join(left)
-        .with(right)
-        .as(ClassResource.fromQualifiedName(ctx.classres().getText()));
-
-    ctx.keepaggregatesexpr().stream()
-        .map(keepStatementVisitor::visitKeepaggregatesexpr)
-        .forEach(joinBuilder::keep);
-    ctx.keepattributesexpr().stream()
-        .map(keepStatementVisitor::visitKeepattributesexpr)
-        .forEach(joinBuilder::keep);
-    ctx.keepcalculatedexpr().stream()
-        .map(keepStatementVisitor::visitKeepcalculatedexpr)
-        .forEach(joinBuilder::keep);
-    ctx.keepexpr().stream()
-        .map(keepStatementVisitor::visitKeepexpr)
-        .forEach(joinBuilder::keep);
-
-    return joinBuilder.done();
-  }
-
-  /**
-   * Creates the {@link OuterJoinExpression} instance contained in a {@code JoinContext}. This
-   * method assumes that the provided {@code ctx} indeed contains an outer join.
-   */
-  private OuterJoinExpression generateOuterJoin(@Nonnull JoinContext ctx) {
-    OuterjoinContext outerJoinContext = ctx.outerjoin();
-
-    ClassResource left = ClassResource.fromQualifiedName(outerJoinContext.classres(0).getText());
-    ClassResource right = ClassResource.fromQualifiedName(outerJoinContext.classres(1).getText());
-
-    OuterJoinBuilder joinBuilder = JoinFactory.createNew()
-        .outer()
-        .join(left)
-        .with(right)
-        .as(ClassResource.fromQualifiedName(ctx.classres().getText()));
-
-    if (outerJoinContext.leftouterjoin() != null) {
-      joinBuilder.leftOuter();
-    } else if (outerJoinContext.rightouterjoin() != null) {
-      joinBuilder.rightOuter();
-    } else {
-      throw new ModelJoinParsingException("Expected either 'left' or 'right' 'outer join'");
-    }
-
-    ctx.keepaggregatesexpr().stream()
-        .map(keepStatementVisitor::visitKeepaggregatesexpr)
-        .forEach(joinBuilder::keep);
-    ctx.keepattributesexpr().stream()
-        .map(keepStatementVisitor::visitKeepattributesexpr)
-        .forEach(joinBuilder::keep);
-    ctx.keepcalculatedexpr().stream()
-        .map(keepStatementVisitor::visitKeepcalculatedexpr)
-        .forEach(joinBuilder::keep);
-    ctx.keepexpr().stream()
-        .map(keepStatementVisitor::visitKeepexpr)
-        .forEach(joinBuilder::keep);
-
-    return joinBuilder.done();
-  }
-
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/KeepStatementVisitor.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/KeepStatementVisitor.java
deleted file mode 100644
index 2e9789d220ded97f3b053e9c1a461ecd29f9d022..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/KeepStatementVisitor.java
+++ /dev/null
@@ -1,307 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.parser.antlr;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-import org.rosi_project.model_sync.model_join.representation.core.AttributePath;
-import org.rosi_project.model_sync.model_join.representation.core.ClassResource;
-import org.rosi_project.model_sync.model_join.representation.core.OCLStatement;
-import org.rosi_project.model_sync.model_join.representation.core.RelativeAttribute;
-import org.rosi_project.model_sync.model_join.representation.core.TypedAttributePath;
-import org.rosi_project.model_sync.model_join.representation.grammar.KeepAggregateExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.KeepAggregateExpression.AggregationType;
-import org.rosi_project.model_sync.model_join.representation.grammar.KeepAttributesExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.KeepCalculatedExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.KeepExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.KeepReferenceExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.KeepSubTypeExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.KeepSuperTypeExpression;
-import org.rosi_project.model_sync.model_join.representation.parser.ModelJoinParsingException;
-import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinBaseVisitor;
-import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.AttrresContext;
-import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.KeepaggregatesexprContext;
-import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.KeepattributesexprContext;
-import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.KeepcalculatedexprContext;
-import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.KeepexprContext;
-import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.KeepincomingexprContext;
-import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.KeepoutgoingexprContext;
-import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.KeepsubtypeexprContext;
-import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.KeepsupertypeexprContext;
-
-/**
- * The {@code KeepStatementVisitor} creates {@link KeepExpression} instances from a parsed {@code
- * ModelJoin} file.
- *
- * @author Rico Bergmann
- */
-public class KeepStatementVisitor extends ModelJoinBaseVisitor<KeepExpression> {
-
-  /**
-   * A simple enumeration of the possible keep statements for compound statements as defined in the
-   * {@code ModelJoin} ANTLR grammar.
-   */
-  private enum KeepExprType {
-
-    /**
-     * The {@code KEEP_TYPE_EXPR} subsumes both {@code keep subtype} as well as {@code keep
-     * supertype} expressions.
-     */
-    KEEP_TYPE_EXPR,
-
-    /**
-     * The {@code KEEP_INCOMING_EXPR} corresponds to a {@code keep incoming reference} statement.
-     */
-    KEEP_INCOMING_EXPR,
-
-    /**
-     * The {@code KEEP_OUTGOING_EXPR} corresponds to a {@code keep outgoing reference} statement.
-     */
-    KEEP_OUTGOING_EXPR
-
-  }
-
-  @Override
-  public KeepExpression visitKeepattributesexpr(KeepattributesexprContext ctx) {
-    return new KeepAttributesExpression(
-        ctx.attrres().stream()
-            .map(AttrresContext::getText)
-            .map(AttributePath::fromQualifiedPath)
-            .collect(ArrayList::new, ArrayList::add, ArrayList::addAll)
-    );
-
-  }
-
-  @Override
-  public KeepExpression visitKeepaggregatesexpr(KeepaggregatesexprContext ctx) {
-    String rawAggregationType = ctx.aggrtype().getText();
-    AggregationType aggregationType = AggregationType.valueOf(rawAggregationType.toUpperCase());
-
-    return new KeepAggregateExpression(
-        aggregationType /* SUM / MAX / MIN etc */,
-        RelativeAttribute.of(ctx.relattr().getText()) /* the attribute in the target relation  */,
-        AttributePath.fromQualifiedPath(ctx.classres().getText()) /* the source attribute */,
-        AttributePath.fromQualifiedPath(ctx.attrres().getText()) /* name in the new ModelJoin */
-    );
-  }
-
-  @Override
-  public KeepExpression visitKeepcalculatedexpr(KeepcalculatedexprContext ctx) {
-    OCLStatement oclExpr = OCLStatement.of(ctx.oclcond().getText());
-
-    return KeepCalculatedExpression //
-        .keepCalculatedAttribute(oclExpr) //
-        .as(TypedAttributePath.fromQualifiedTypedPath(ctx.typedattrres().getText())
-        );
-  }
-
-  @Override
-  public KeepExpression visitKeepexpr(KeepexprContext ctx) {
-    KeepExprType keepExprType = determineExpressionTypeFor(ctx);
-
-    switch (keepExprType) {
-      case KEEP_TYPE_EXPR:
-        return buildKeepTypeExpressionFor(ctx);
-      case KEEP_INCOMING_EXPR:
-        return buildKeepIncomingReferenceExpressionFor(ctx);
-      case KEEP_OUTGOING_EXPR:
-        return buildKeepOutgoingReferenceExpressionFor(ctx);
-      default:
-        throw new AssertionError(keepExprType);
-    }
-  }
-
-  /**
-   * Checks, which kind of expression is specified in a specific {@code KeepexprContext}.
-   */
-  private KeepExprType determineExpressionTypeFor(KeepexprContext ctx) {
-
-    /*
-     * From the ANTLR grammar we know that exactly one of the IF cases has to hold
-     */
-    if (ctx.keeptypeexpr() != null) {
-      return KeepExprType.KEEP_TYPE_EXPR;
-    } else if (ctx.keepincomingexpr() != null) {
-      return KeepExprType.KEEP_INCOMING_EXPR;
-    } else if (ctx.keepoutgoingexpr() != null) {
-      return KeepExprType.KEEP_OUTGOING_EXPR;
-    } else {
-      throw new ModelJoinParsingException(
-          "Expected either 'keep reference' or 'keep type'  expression: " + ctx);
-    }
-  }
-
-  /**
-   * Creates the appropriate {@link KeepExpression} for a {@code KeepexprContext}.
-   */
-  private KeepExpression buildKeepTypeExpressionFor(KeepexprContext ctx) {
-    if (ctx.keeptypeexpr().keepsubtypeexpr() != null) {
-      return buildKeepSubtypeExpressionFor(ctx);
-    } else if (ctx.keeptypeexpr().keepsupertypeexpr() != null) {
-      return buildKeepSupertypeExpressionFor(ctx);
-    } else {
-      throw new ModelJoinParsingException(
-          "Expected either 'keep supertype' or 'keep subtype'  expression: " + ctx);
-    }
-  }
-
-  /**
-   * Creates the {@link KeepReferenceExpression} instance contained in a {@code KeepexprContext}.
-   * This method assumes that the provided {@code ctx} indeed contains a keep incoming reference
-   * statement.
-   */
-  private KeepReferenceExpression buildKeepIncomingReferenceExpressionFor(KeepexprContext ctx) {
-    KeepincomingexprContext incomingCtx = ctx.keepincomingexpr();
-
-    AttributePath attributeToKeep = AttributePath
-        .fromQualifiedPath(incomingCtx.attrres().getText());
-
-    List<KeepExpression> nestedExpressions = ctx.keepattributesexpr().stream()
-        .map(this::visitKeepattributesexpr)
-        .collect(Collectors.toList());
-
-    nestedExpressions.addAll(ctx.keepaggregatesexpr().stream()
-        .map(this::visitKeepaggregatesexpr)
-        .collect(Collectors.toList())
-    );
-
-    nestedExpressions.addAll(ctx.keepexpr().stream()
-        .map(this::visitKeepexpr)
-        .collect(Collectors.toList())
-    );
-
-    KeepReferenceExpression.KeepReferenceBuilder expressionBuilder = KeepReferenceExpression.keep()
-        .incoming(attributeToKeep);
-
-    ClassResource targetClass;
-    if (incomingCtx.classres() != null) {
-      targetClass = ClassResource.fromQualifiedName(incomingCtx.classres().getText());
-    } else {
-      targetClass = attributeToKeep.getContainingClass();
-    }
-
-    expressionBuilder.as(targetClass);
-    nestedExpressions.forEach(expressionBuilder::keep);
-
-    return expressionBuilder.buildExpression();
-  }
-
-  /**
-   * Creates the {@link KeepReferenceExpression} instance contained in a {@code KeepexprContext}.
-   * This method assumes that the provided {@code ctx} indeed contains a keep outgoing reference
-   * statement.
-   */
-  private KeepReferenceExpression buildKeepOutgoingReferenceExpressionFor(KeepexprContext ctx) {
-    KeepoutgoingexprContext outgoingCtx = ctx.keepoutgoingexpr();
-
-    AttributePath attributeToKeep = AttributePath
-        .fromQualifiedPath(outgoingCtx.attrres().getText());
-
-    List<KeepExpression> nestedExpressions = ctx.keepattributesexpr().stream()
-        .map(this::visitKeepattributesexpr)
-        .collect(Collectors.toList());
-
-    nestedExpressions.addAll(ctx.keepaggregatesexpr().stream()
-        .map(this::visitKeepaggregatesexpr)
-        .collect(Collectors.toList())
-    );
-
-    nestedExpressions.addAll(ctx.keepexpr().stream()
-        .map(this::visitKeepexpr)
-        .collect(Collectors.toList())
-    );
-
-    KeepReferenceExpression.KeepReferenceBuilder expressionBuilder = KeepReferenceExpression.keep()
-        .outgoing(attributeToKeep);
-
-    ClassResource targetClass;
-    if (outgoingCtx.classres() != null) {
-      targetClass = ClassResource.fromQualifiedName(outgoingCtx.classres().getText());
-    } else {
-      targetClass = attributeToKeep.getContainingClass();
-    }
-
-    expressionBuilder.as(targetClass);
-    nestedExpressions.forEach(expressionBuilder::keep);
-
-    return expressionBuilder.buildExpression();
-  }
-
-  /**
-   * Creates the {@link KeepSubTypeExpression} instance contained in a {@code KeepexprContext}. This
-   * method assumes that the provided {@code ctx} indeed contains a keep subtype statement.
-   */
-  private KeepSubTypeExpression buildKeepSubtypeExpressionFor(KeepexprContext ctx) {
-    KeepsubtypeexprContext subtypeCtx = ctx.keeptypeexpr().keepsubtypeexpr();
-
-    ClassResource typeToKeep = ClassResource.fromQualifiedName(subtypeCtx.classres(0).getText());
-
-    List<KeepExpression> nestedExpressions = ctx.keepattributesexpr().stream()
-        .map(this::visitKeepattributesexpr)
-        .collect(Collectors.toList());
-
-    nestedExpressions.addAll(ctx.keepaggregatesexpr().stream()
-        .map(this::visitKeepaggregatesexpr)
-        .collect(Collectors.toList())
-    );
-
-    nestedExpressions.addAll(ctx.keepexpr().stream()
-        .map(this::visitKeepexpr)
-        .collect(Collectors.toList())
-    );
-
-    KeepSubTypeExpression.KeepSubTypeBuilder expressionBuilder = KeepSubTypeExpression.keep()
-        .subtype(typeToKeep);
-
-    ClassResource targetClass;
-    if (subtypeCtx.classres() != null) {
-      targetClass = ClassResource.fromQualifiedName(subtypeCtx.classres(1).getText());
-    } else {
-      targetClass = typeToKeep;
-    }
-
-    expressionBuilder.as(targetClass);
-    nestedExpressions.forEach(expressionBuilder::keep);
-
-    return expressionBuilder.buildExpression();
-  }
-
-  /**
-   * Creates the {@link KeepSuperTypeExpression} instance contained in a {@code KeepexprContext}.
-   * This method assumes that the provided {@code ctx} indeed contains a keep supertype statement.
-   */
-  private KeepSuperTypeExpression buildKeepSupertypeExpressionFor(KeepexprContext ctx) {
-    KeepsupertypeexprContext supertypeCtx = ctx.keeptypeexpr().keepsupertypeexpr();
-
-    ClassResource typeToKeep = ClassResource.fromQualifiedName(supertypeCtx.classres(0).getText());
-
-    List<KeepExpression> nestedExpressions = ctx.keepattributesexpr().stream()
-        .map(this::visitKeepattributesexpr)
-        .collect(Collectors.toList());
-
-    nestedExpressions.addAll(ctx.keepaggregatesexpr().stream()
-        .map(this::visitKeepaggregatesexpr)
-        .collect(Collectors.toList())
-    );
-
-    nestedExpressions.addAll(ctx.keepexpr().stream()
-        .map(this::visitKeepexpr)
-        .collect(Collectors.toList())
-    );
-
-    KeepSuperTypeExpression.KeepSuperTypeBuilder expressionBuilder = KeepSuperTypeExpression.keep()
-        .supertype(typeToKeep);
-
-    ClassResource targetClass;
-    if (supertypeCtx.classres() != null) {
-      targetClass = ClassResource.fromQualifiedName(supertypeCtx.classres(1).getText());
-    } else {
-      targetClass = typeToKeep;
-    }
-
-    expressionBuilder.as(targetClass);
-    nestedExpressions.forEach(expressionBuilder::keep);
-
-    return expressionBuilder.buildExpression();
-  }
-
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/ModelJoinVisitor.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/ModelJoinVisitor.java
deleted file mode 100644
index f1883fa77954a74ed677d8a5b6cc358ca2721946..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/ModelJoinVisitor.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.parser.antlr;
-
-import org.rosi_project.model_sync.model_join.representation.grammar.ModelJoinExpression;
-import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinBaseVisitor;
-import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.ModeljoinContext;
-import org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder;
-
-/**
- * The {@code ModelJoinVisitor} creates a {@link ModelJoinExpression} instances from a parsed {@code
- * ModelJoin} file.
- *
- * @author Rico Bergmann
- */
-public class ModelJoinVisitor extends ModelJoinBaseVisitor<ModelJoinExpression> {
-
-  @Override
-  public ModelJoinExpression visitModeljoin(ModeljoinContext ctx) {
-    JoinStatementVisitor joinVisitor = new JoinStatementVisitor();
-    ModelJoinBuilder modelJoinBuilder = ModelJoinBuilder.createNewModelJoin();
-
-    ctx.join().stream() //
-        .map(joinVisitor::visitJoin) //
-        .forEach(modelJoinBuilder::add);
-
-    return modelJoinBuilder.build();
-  }
-
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/legacy/DefaultModelJoinParser.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/legacy/DefaultModelJoinParser.java
deleted file mode 100644
index 25f4b9ce3871862e570befcb4f28ad761f467345..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/legacy/DefaultModelJoinParser.java
+++ /dev/null
@@ -1,187 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.parser.legacy;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.Optional;
-import java.util.regex.Pattern;
-import javax.annotation.Nonnull;
-import org.rosi_project.model_sync.model_join.representation.grammar.ModelJoinExpression;
-import org.rosi_project.model_sync.model_join.representation.parser.ModelJoinParser;
-import org.rosi_project.model_sync.model_join.representation.parser.ModelJoinParsingException;
-import org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder;
-
-/**
- * The {@code DefaultModelJoinParser} reads a {@code ModelJoin} file from disk and creates matching
- * representation for it.
- *
- * @author Rico Bergmann
- */
-@Deprecated
-public class DefaultModelJoinParser {
-
-  /**
-   * Converts the {@code ModelJoin} file into a {@link ModelJoinExpression}, wrapped into an {@code
-   * Optional}. If parsing fails, an empty {@code Optional} will be returned.
-   */
-  @Nonnull
-  public static Optional<ModelJoinExpression> read(@Nonnull File modelFile) {
-    DefaultModelJoinParser parser = new DefaultModelJoinParser(modelFile, ErrorReportingStrategy.OPTIONAL);
-    return parser.run();
-  }
-
-  /**
-   * Converts the {@code ModelJoin} file into a {@link ModelJoinExpression}. If parsing fails, a
-   * {@link ModelJoinParsingException} will be thrown.
-   *
-   * @throws ModelJoinParsingException if the model may not be parsed for some reason.
-   */
-  @Nonnull
-  public static ModelJoinExpression readOrThrow(@Nonnull File modelFile) {
-    DefaultModelJoinParser parser = new DefaultModelJoinParser(modelFile, ErrorReportingStrategy.EXCEPTION);
-    Optional<ModelJoinExpression> result = parser.run();
-
-    if (result.isPresent()) {
-      return result.get();
-    } else {
-      /*
-       * Theoretically, the parser should throw the exception by itself, so this code should never
-       * actually run. It is merely here for safety purposes (unchecked access of Optional.get())
-       */
-      throw new ModelJoinParsingException("Result not present but no exception was thrown either");
-    }
-  }
-
-  /**
-   * Indicates what should happen if parsing fails.
-   */
-  enum ErrorReportingStrategy {
-
-    /**
-     * On failure an empty {@code Optional} should be returned.
-     */
-    OPTIONAL,
-
-    /**
-     * On failure an {@link ModelJoinParsingException} should be thrown.
-     */
-    EXCEPTION
-  }
-
-  private static final Pattern EMPTY_LINE = Pattern.compile("^\\s*$");
-  private static final Pattern IMPORT_STATEMENT = Pattern.compile("^import .*");
-  private static final Pattern TARGET_STATEMENT = Pattern.compile("^target .*");
-  private static final Pattern JOIN_STATEMENT = Pattern
-      .compile("^(((left|right) outer)|theta|natural) join .*");
-
-  @Nonnull
-  private final File modelFile;
-
-  @Nonnull
-  private final ErrorReportingStrategy errorReportingStrategy;
-
-  /**
-   * Full constructor.
-   *
-   * @param modelFile the file to parse
-   * @param errorReportingStrategy what to do in case an error occurs.
-   */
-  private DefaultModelJoinParser(@Nonnull File modelFile,
-      @Nonnull ErrorReportingStrategy errorReportingStrategy) {
-    this.modelFile = modelFile;
-    this.errorReportingStrategy = errorReportingStrategy;
-  }
-
-  /**
-   * Creates the {@code ModelJoin} representation from the {@code modelFile}.
-   * <p>
-   * Depending on the selected {@code errorReportingStrategy} either an Exception will be thrown, or
-   * an empty {@code Optional} will be returned if something goes wrong.
-   */
-  private Optional<ModelJoinExpression> run() {
-    ModelJoinExpression resultingModel;
-    try (FileInputStream modelInputStream = new FileInputStream(modelFile);
-        InputStreamReader modelInputReader = new InputStreamReader(modelInputStream);
-        BufferedReader bufferedModelReader = new BufferedReader(modelInputReader)) {
-
-      ModelJoinBuilder modelJoinBuilder = ModelJoinBuilder.createNewModelJoin();
-      readModelFileAndPopulateBuilder(bufferedModelReader, modelJoinBuilder);
-      resultingModel = modelJoinBuilder.build();
-
-    } catch (ModelJoinParsingException e) {
-      switch (errorReportingStrategy) {
-        case OPTIONAL:
-          return Optional.empty();
-        case EXCEPTION:
-          throw e;
-        default:
-          throw new AssertionError(errorReportingStrategy);
-      }
-    } catch (IOException e) {
-      switch (errorReportingStrategy) {
-        case OPTIONAL:
-          return Optional.empty();
-        case EXCEPTION:
-          throw new ModelJoinParsingException(e);
-        default:
-          throw new AssertionError(errorReportingStrategy);
-      }
-    }
-    return Optional.of(resultingModel);
-  }
-
-  /**
-   * Reads the {@code modelFile} and constructs the corresponding {@code ModelJoin} on the fly.
-   * <p>
-   * On error, an {@code IOException} or an {@link ModelJoinParsingException} will be thrown.
-   *
-   * @throws ModelJoinParsingException if the model file's content are malformed or another
-   *     component failed
-   * @throws IOException if the model file might not be read any further
-   */
-  private void readModelFileAndPopulateBuilder(BufferedReader modelReader,
-      ModelJoinBuilder modelBuilder) throws IOException {
-    String currentLine;
-    while ((currentLine = modelReader.readLine()) != null) {
-      if (lineShouldBeSkipped(currentLine)) {
-        // the line should be skipped. So we do nothing.
-        continue;
-      } else if (lineStartsJoinDeclaration(currentLine)) {
-        // a new join is being declared. Delegate to the join parser to handle the rest.
-        JoinParser joinParser = new JoinParser(currentLine, modelReader);
-        modelBuilder.add(joinParser.run());
-      } else {
-        // we do not know what to do with the current line. Should abort.
-        throw new ModelJoinParsingException("Unexpected line: '" + currentLine + "'");
-      }
-    }
-  }
-
-  /**
-   * Checks, whether the parser should consider the given {@code line} any further, or just ignore
-   * it.
-   * <p>
-   * A line should be skipped, iff.
-   * <ul>
-   * <li>It only consists of whitespace characters</li>
-   * <li>It is an {@code import statement} (as those are not yet considered in the current {@code
-   * ModelJoin} abstraction)</li>
-   * <li>It is a {@code target statement} (as those are not yet considered in the current {@code
-   * ModelJoin} abstraction)</li>
-   * </ul>
-   */
-  private boolean lineShouldBeSkipped(String line) {
-    return EMPTY_LINE.matcher(line).matches() //
-        || IMPORT_STATEMENT.matcher(line).matches() //
-        || TARGET_STATEMENT.matcher(line).matches();
-  }
-
-  /**
-   * Checks, whether the given {@code line} is the beginning of a {@code join statement}.
-   */
-  private boolean lineStartsJoinDeclaration(String line) {
-    return JOIN_STATEMENT.matcher(line).matches();
-  }
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/legacy/JoinParser.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/legacy/JoinParser.java
deleted file mode 100644
index ee32b6167aa20c1785f1671af0ac52f1a2c46b75..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/legacy/JoinParser.java
+++ /dev/null
@@ -1,254 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.parser.legacy;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.util.Collection;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import javax.annotation.Nonnull;
-import org.rosi_project.model_sync.model_join.representation.core.ClassResource;
-import org.rosi_project.model_sync.model_join.representation.core.OCLConstraint;
-import org.rosi_project.model_sync.model_join.representation.grammar.JoinExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.KeepExpression;
-import org.rosi_project.model_sync.model_join.representation.parser.ModelJoinParsingException;
-import org.rosi_project.model_sync.model_join.representation.util.JoinFactory;
-import org.rosi_project.model_sync.model_join.representation.util.JoinFactory.NaturalJoinBuilder;
-import org.rosi_project.model_sync.model_join.representation.util.JoinFactory.OuterJoinBuilder;
-import org.rosi_project.model_sync.model_join.representation.util.JoinFactory.ThetaJoinBuilder;
-
-/**
- * The {@code JoinParser} takes care of reading an individual {@code join statement} and creates the
- * corresponding {@link JoinExpression}.
- * <p>
- * This class is primarily intended to be created and invoked by the {@link DefaultModelJoinParser} only as
- * will modify the state of that as well.
- *
- * @author Rico Bergmann
- */
-@Deprecated
-class JoinParser {
-
-  private static final String START_OF_JOIN_BLOCK_DELIMITER = "{";
-  private static final String JOIN_TYPE_THETA = "theta";
-  private static final Pattern JOIN_TYPE_DECLARATION = Pattern
-      .compile(".*(?<type>((?<outertype>(right |left )outer)|theta|natural)) join .*");
-  private static final Pattern LEFT_SOURCE_DECLARATION = Pattern
-      .compile(".*join (?<leftsource>[\\w\\\\.]*) .*");
-  private static final Pattern RIGHT_SOURCE_DECLARATION = Pattern
-      .compile(".*with (?<rightsource>[\\w\\\\.]*) .*");
-  private static final Pattern TARGET_DECLARATION = Pattern
-      .compile(".*as (?<target>[\\w\\\\.]*)( .*|\\{)");
-  private static final Pattern THETA_PREDICATE_DECLARATION = Pattern
-      .compile(".*where (?<predicate>[\\w\\\\.]*)\\{");
-
-  @Nonnull
-  private final String startingLine;
-
-  @Nonnull
-  private final BufferedReader modelReader;
-
-  private boolean hasReadStartOfJoinBlockCharacter = false;
-
-  /**
-   * Full constructor.
-   *
-   * @param startingLine the line that was last read by the {@link DefaultModelJoinParser} and should
-   *     therefore become the starting point for {@code this} parser.
-   * @param modelReader the reader that provides access to the following lines in the {@code
-   *     ModelJoin} file currently being read.
-   */
-  JoinParser(@Nonnull String startingLine, @Nonnull BufferedReader modelReader) {
-    this.startingLine = startingLine;
-    this.modelReader = modelReader;
-  }
-
-  /**
-   * Creates the {@link JoinExpression} from the current {@code join statement}.
-   * <p>
-   * If something goes wrong, either an {@code IOException} will be thrown directly or a {@link
-   * ModelJoinParsingException} is used.
-   */
-  @Nonnull
-  public JoinExpression run() throws IOException {
-
-    // first, we will determine the Join type
-
-    Matcher joinTypeDeclarationMatcher = JOIN_TYPE_DECLARATION.matcher(startingLine);
-
-    if (!joinTypeDeclarationMatcher.matches()) {
-      throw new ModelJoinParsingException(
-          "Expected beginning of a Join declaration on '" + startingLine + "'");
-    }
-
-    String joinType = joinTypeDeclarationMatcher.group("type");
-    String outerJoinType = "";
-
-    if (joinType.equals("outer")) {
-      outerJoinType = joinTypeDeclarationMatcher.group("outertype");
-    }
-
-    // second, we will try to extract all necessary info from the first line
-
-    String leftSource = null;
-    String rightSource = null;
-    String target = null;
-    String thetaPredicate = null;
-
-    Matcher leftSourceMatcher = LEFT_SOURCE_DECLARATION.matcher(startingLine);
-    Matcher rightSourceMatcher = RIGHT_SOURCE_DECLARATION.matcher(startingLine);
-    Matcher targetMatcher = TARGET_DECLARATION.matcher(startingLine);
-    Matcher thetaPredicateMatcher = THETA_PREDICATE_DECLARATION.matcher(startingLine);
-
-    final int necessaryComponents;
-    int foundComponents = 0;
-
-    if (leftSourceMatcher.matches()) {
-      leftSource = leftSourceMatcher.group("leftsource");
-      foundComponents++;
-    }
-
-    if (rightSourceMatcher.matches()) {
-      rightSource = rightSourceMatcher.group("rightsource");
-      foundComponents++;
-    }
-
-    if (targetMatcher.matches()) {
-      target = targetMatcher.group("target");
-      foundComponents++;
-    }
-
-    if (joinType.equals(JOIN_TYPE_THETA)) {
-      necessaryComponents = 4;
-      if (thetaPredicateMatcher.matches()) {
-        thetaPredicate = thetaPredicateMatcher.group("predicate");
-        foundComponents++;
-      }
-    } else {
-      necessaryComponents = 3;
-    }
-
-    // in case all information is present on the first line, we are done already
-
-    if (startingLine.contains(START_OF_JOIN_BLOCK_DELIMITER)) {
-      // TODO could the start character be part of an OCL statement?
-      hasReadStartOfJoinBlockCharacter = true;
-    }
-
-    // otherwise, we need to read the following lines as well
-
-    String currentLine = "";
-    while (!hasReadStartOfJoinBlockCharacter //
-        && foundComponents < necessaryComponents //
-        && (currentLine = modelReader.readLine()) != null) {
-
-      // again, we try to extract as much as possible of the info we need
-      // however, we now also have to check, whether we have already specified a component, as well
-
-      leftSourceMatcher = LEFT_SOURCE_DECLARATION.matcher(currentLine);
-      if (leftSource == null && leftSourceMatcher.matches()) {
-        leftSource = leftSourceMatcher.group("leftsource");
-        foundComponents++;
-      }
-
-      rightSourceMatcher = RIGHT_SOURCE_DECLARATION.matcher(currentLine);
-      if (rightSource == null && rightSourceMatcher.matches()) {
-        rightSource = rightSourceMatcher.group("rightsource");
-        foundComponents++;
-      }
-
-      targetMatcher = TARGET_DECLARATION.matcher(currentLine);
-      if (target == null && targetMatcher.matches()) {
-        target = targetMatcher.group("target");
-      }
-
-      if (joinType.equals(JOIN_TYPE_THETA)) {
-        thetaPredicateMatcher = THETA_PREDICATE_DECLARATION.matcher(currentLine);
-        if (thetaPredicate == null && thetaPredicateMatcher.matches()) {
-          thetaPredicate = thetaPredicateMatcher.group("predicate");
-          foundComponents++;
-        }
-      }
-
-      if (currentLine.contains(START_OF_JOIN_BLOCK_DELIMITER)) {
-        hasReadStartOfJoinBlockCharacter = true;
-      }
-    }
-
-    // if we found the beginning of the Join body, but did not read all our information, the
-    // ModelJoin file is flawed
-
-    if (foundComponents < necessaryComponents) {
-      throw new ModelJoinParsingException(
-          "ModelJoin grammar violation: found components " + foundComponents + " but expected "
-              + necessaryComponents);
-    }
-
-    // otherwise we are ready to go. So we skip forward until the Join body is reached.
-
-    while (!hasReadStartOfJoinBlockCharacter && (currentLine = modelReader.readLine()) != null) {
-      if (currentLine.contains(START_OF_JOIN_BLOCK_DELIMITER)) {
-        hasReadStartOfJoinBlockCharacter = true;
-      }
-    }
-
-    // if we read everything, but did not find the Join body, the ModelJoin file is flawed again
-
-    if (!hasReadStartOfJoinBlockCharacter) {
-      throw new ModelJoinParsingException(
-          "Expected start of join block but could not read any further");
-    }
-
-    // if not all components are initialized by now, we are working on a flawed ModelJoin file
-
-    if (currentLine == null || leftSource == null || rightSource == null || target == null) {
-      throw new ModelJoinParsingException(
-          "Not all required information was found but could not read any further");
-    }
-
-    // at this point the declaration of the join statement is valid
-    // therefore we want the keep expressions it contains. This is the KeepParser's job.
-
-    KeepParser keepParser = new KeepParser(currentLine, modelReader);
-    Collection<KeepExpression> keeps = keepParser.run();
-
-    // finally we have to create the correct JoinExpression
-
-    JoinFactory joinFactory = JoinFactory.createNew();
-    switch (joinType) {
-      case "outer":
-        OuterJoinBuilder outerJoinBuilder = joinFactory.outer();
-        if (outerJoinType.equals("left")) {
-          outerJoinBuilder.leftOuter();
-        } else if (outerJoinType.equals("right")) {
-          outerJoinBuilder.rightOuter();
-        } else {
-          throw new ModelJoinParsingException("Unknown direction for outer join: " + outerJoinType);
-        }
-        outerJoinBuilder //
-            .join(ClassResource.fromQualifiedName(leftSource)) //
-            .with(ClassResource.fromQualifiedName(rightSource)) //
-            .as(ClassResource.fromQualifiedName(target));
-        keeps.forEach(outerJoinBuilder::keep);
-        return outerJoinBuilder.done();
-      case "theta":
-        ThetaJoinBuilder thetaJoinBuilder = joinFactory //
-            .theta() //
-            .join(ClassResource.fromQualifiedName(leftSource)) //
-            .with(ClassResource.fromQualifiedName(rightSource)) //
-            .as(ClassResource.fromQualifiedName(target)) //
-            .where(OCLConstraint.of(thetaPredicate));
-        keeps.forEach(thetaJoinBuilder::keep);
-        return thetaJoinBuilder.done();
-      case "natural":
-        NaturalJoinBuilder naturalJoinBuilder = joinFactory //
-            .natural() //
-            .join(ClassResource.fromQualifiedName(leftSource)) //
-            .with(ClassResource.fromQualifiedName(rightSource)) //
-            .as(ClassResource.fromQualifiedName(target));
-        keeps.forEach(naturalJoinBuilder::keep);
-        return naturalJoinBuilder.done();
-      default:
-        throw new ModelJoinParsingException("Unknown join type: " + joinType);
-    }
-  }
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/legacy/KeepParser.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/legacy/KeepParser.java
deleted file mode 100644
index ac82f383b79ed8a38b3a7590daf4bbe5843d4d99..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/legacy/KeepParser.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.parser.legacy;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Optional;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import javax.annotation.Nonnull;
-import org.rosi_project.model_sync.model_join.representation.core.AttributePath;
-import org.rosi_project.model_sync.model_join.representation.grammar.KeepAttributesExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.KeepExpression;
-import org.rosi_project.model_sync.model_join.representation.parser.ModelJoinParsingException;
-
-/**
- * The {@code KeepParser} takes care of reading the {@code keep statements} and creating the
- * corresponding {@link KeepExpression}s for the body of an {@code join statement}.
- * <p>
- * This class is primarily intended to be created and invoked by the {@link JoinParser} only as will
- * modify the state of that as well.
- *
- * @author Rico Bergmann
- */
-@Deprecated
-class KeepParser {
-
-  private static final String END_OF_JOIN_BLOCK_DELIMITER = "}";
-  private static final Pattern KEEP_ATTRIBUTE_DECLARATION = Pattern
-      .compile(".*keep attributes\\W*(?<attribute>[\\w\\\\.]*)$");
-
-  @Nonnull
-  private final String startingLine;
-
-  @Nonnull
-  private final BufferedReader modelReader;
-
-  private boolean hasReadEndOfJoinBlockDelimiter = false;
-
-  /**
-   * Full constructor.
-   * @param startingLine the line that was last read by the {@link JoinParser} and should
-   *     therefore become the starting point for {@code this} parser.
-   * @param modelReader the reader that provides access to the following lines in the {@code
-   *     ModelJoin} file currently being read.
-   */
-  KeepParser(@Nonnull String startingLine, @Nonnull BufferedReader modelReader) {
-    this.startingLine = startingLine;
-    this.modelReader = modelReader;
-  }
-
-  /**
-   * Creates the {@link KeepExpression}s for the current {@code join statement}.
-   * <p>
-   * If something goes wrong, either an {@code IOException} will be thrown directly or a {@link
-   * ModelJoinParsingException} is used.
-   */
-  @Nonnull
-  public Collection<KeepExpression> run() throws IOException {
-    List<KeepExpression> detectedKeeps = new LinkedList<>();
-    Matcher keepMatcher = KEEP_ATTRIBUTE_DECLARATION.matcher(startingLine);
-
-    parseLine(startingLine, keepMatcher).ifPresent(detectedKeeps::add);
-
-    String currentLine;
-    while (!hasReadEndOfJoinBlockDelimiter && (currentLine = modelReader.readLine()) != null) {
-      keepMatcher = KEEP_ATTRIBUTE_DECLARATION.matcher(currentLine);
-      parseLine(currentLine, keepMatcher).ifPresent(detectedKeeps::add);
-    }
-
-    return detectedKeeps;
-  }
-
-  /**
-   * Tries to create a {@link KeepExpression} for a single {@code keep statement} written on the
-   * {@code current line}.
-   * <p>
-   * If there is no such statement, an empty {@code Optional} will be returned.
-   * <p>
-   * If the line indicates the end of the keep-block, the state of {@code this} parser will be
-   * updated accordingly.
-   */
-  @Nonnull
-  private Optional<KeepExpression> parseLine(String currentLine, Matcher keepMatcher) {
-    Optional<KeepExpression> result = Optional.empty();
-    if (keepMatcher.matches()) {
-      AttributePath attribute = AttributePath.fromQualifiedPath(keepMatcher.group("attribute"));
-      result = Optional.of(KeepAttributesExpression.keepAttributes(attribute));
-    }
-
-    if (currentLine.contains(END_OF_JOIN_BLOCK_DELIMITER)) {
-      hasReadEndOfJoinBlockDelimiter = true;
-    }
-    return result;
-  }
-
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/util/Assert.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/util/Assert.java
deleted file mode 100644
index d72ecca9b380b86828c5134808cef2e48bc46cd8..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/util/Assert.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.util;
-
-import javax.annotation.Nonnull;
-
-/**
- * Utility class to provide a number of useful assertion mechanisms.
- * <p>
- * On failure, an {@code AssertionError} with a dedicated message will be thrown.
- *
- * @author Rico Bergmann
- */
-public class Assert {
-
-  /**
-   * Ensures that an object is not {@code null}.
-   */
-  public static void notNull(Object obj, @Nonnull String failureMessage) {
-    if (obj == null) {
-      throw new AssertionError(failureMessage);
-    }
-  }
-
-  /**
-   * Ensures that none of the arguments is {@code null}.
-   */
-  public static void noNullArguments(@Nonnull String failureMessage, Object... arguments) {
-    if (arguments == null) {
-      throw new AssertionError("Vararg arguments may not be null");
-    }
-    for (Object arg : arguments) {
-      if (arg == null) {
-        throw new AssertionError(failureMessage);
-      }
-    }
-  }
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/util/Functional.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/util/Functional.java
deleted file mode 100644
index 853ee96122a43dfe41d4269dcaf6feb592b284d9..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/util/Functional.java
+++ /dev/null
@@ -1,235 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.util;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-import java.util.function.Function;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.swing.text.html.Option;
-
-/**
- * Contains a number of useful classes to mimic behaviour from functional programming languages in
- * Java.
- *
- * @author Rico Bergmann
- */
-public class Functional {
-
-  /**
-   * Emulates a dispatch on the concrete type of an object. Depending on the type, different control
-   * paths will be executed.
-   *
-   * @param something the object to match on
-   */
-  @Nonnull
-  public static <R> FunctionalMatch<R> match(@Nonnull Object something) {
-    return new FunctionalMatch<>(something);
-  }
-
-  /**
-   *
-   * @author Rico Bergmann
-   *
-   * @param <R>
-   */
-  public static class FunctionalMatch<R> extends Functional {
-
-    @Nonnull
-    private final Object matchInstance;
-
-    @Nonnull
-    private final List<Pair<Class<?>, CaseResult<R>>> functions;
-
-    @Nullable
-    private CaseResult<R> defaultAction;
-
-    /**
-     *
-     * @param matchInstance
-     */
-    private FunctionalMatch(@Nonnull Object matchInstance) {
-      Assert.notNull(matchInstance, "Object to match on may not be null");
-      this.matchInstance = matchInstance;
-      this.functions = new ArrayList<>();
-    }
-
-    /**
-     * @param clazz
-     * @param action
-     * @return
-     */
-    @SuppressWarnings("unchecked")
-    public <T> FunctionalMatch<R> caseOf(@Nonnull Class<T> clazz, @Nonnull Function<T, R> action) {
-      Assert.notNull(clazz, "Class to match on may not be null");
-      Assert.notNull(action, "Action to perform may not be null");
-      functions.add(
-          Pair.of(clazz, new RunnableCaseResult<>((Function<Object, R>) action, matchInstance)));
-      return this;
-    }
-
-    /**
-     * @param clazz
-     * @param result
-     * @return
-     */
-    public <T> FunctionalMatch<R> caseOf(@Nonnull Class<T> clazz, @Nonnull R result) {
-      Assert.notNull(clazz, "Class to match on may not be null");
-      Assert.notNull(result, "Match result may not be null");
-      functions.add(Pair.of(clazz, new StaticCaseResult<>(result)));
-      return this;
-    }
-
-    /**
-     * @param action
-     * @return
-     */
-    public FunctionalMatch<R> defaultCase(@Nonnull Function<? super Object, R> action) {
-      Assert.notNull(action, "Default action may not be null");
-      this.defaultAction = new RunnableCaseResult<>(action, matchInstance);
-      return this;
-    }
-
-    /**
-     * @param result
-     * @return
-     */
-    public FunctionalMatch<R> defaultCase(R result) {
-      Assert.notNull(result, "Match result may not be null");
-      this.defaultAction = new StaticCaseResult<>(result);
-      return this;
-    }
-
-    /**
-     * Performs the match.
-     * <p>
-     * This will check for the first case to which the match object is assignable and execute the
-     * associated action.
-     *
-     * @return the result of the action or {@code null} if no matching case was specified.
-     */
-    public R run() {
-      try {
-        R res = runOrThrow();
-        return res;
-      } catch (MatchException e) {
-        return null;
-      }
-    }
-
-    public Optional<R> tryRun() {
-      try {
-        R res = runOrThrow();
-        return Optional.of(res);
-      } catch (MatchException e) {
-        return Optional.empty();
-      }
-    }
-
-    /**
-     * Attempts to perform the match.
-     * <p>
-     * This will check for the first case to which the match object is assignable and execute the
-     * associated action. If no matching action was specified, an exception will be raised.
-     *
-     * @return the result of the action or {@code null} if no matching case was specified.
-     * @throws MatchException if no matching action was given.
-     */
-    public R runOrThrow() {
-      for (Pair<Class<?>, CaseResult<R>> caseEntry : functions) {
-        Class<?> entryClass = caseEntry.getFirst();
-        if (entryClass.isAssignableFrom(matchInstance.getClass())) {
-          return caseEntry.getSecond().calculate();
-        }
-      }
-      if (defaultAction != null) {
-        return defaultAction.calculate();
-      }
-      throw new MatchException(matchInstance.getClass(), "No case specified");
-    }
-
-    private static abstract class CaseResult<R> {
-
-      abstract R calculate();
-
-    }
-
-    private static class RunnableCaseResult<R> extends CaseResult<R> {
-
-      private final Function<Object, R> action;
-      private final Object param;
-
-      /**
-       * @param action
-       * @param param
-       */
-      RunnableCaseResult(@Nonnull Function<Object, R> action, @Nonnull Object param) {
-        Assert.notNull(action, "Action may not be null");
-        Assert.notNull(param, "Param may not be null");
-        this.action = action;
-        this.param = param;
-      }
-
-      /*
-       * (non-Javadoc)
-       *
-       * @see de.naju.adebar.util.Functional.FunctionalMatch.CaseResult#calculate()
-       */
-      @Override
-      R calculate() {
-        return action.apply(param);
-      }
-
-    }
-
-    private static class StaticCaseResult<R> extends CaseResult<R> {
-
-      private final R result;
-
-      /**
-       * @param result
-       */
-      public StaticCaseResult(R result) {
-        this.result = result;
-      }
-
-      /*
-       * (non-Javadoc)
-       *
-       * @see de.naju.adebar.util.Functional.FunctionalMatch.CaseResult#calculate()
-       */
-      @Override
-      R calculate() {
-        return result;
-      }
-
-    }
-
-  }
-
-  public static class MatchException extends RuntimeException {
-
-    private static final long serialVersionUID = -3903882205980399140L;
-
-    private final Class<?> actualClass;
-
-    MatchException(Class<?> actualClass) {
-      this.actualClass = actualClass;
-    }
-
-    MatchException(Class<?> actualClass, String message) {
-      super(message);
-      this.actualClass = actualClass;
-    }
-
-    /**
-     * @return the actualClass
-     */
-    public Class<?> getActualClass() {
-      return actualClass;
-    }
-
-  }
-
-
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/util/JoinFactory.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/util/JoinFactory.java
deleted file mode 100644
index bd873738be32d3169868662f1f048e01480db08e..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/util/JoinFactory.java
+++ /dev/null
@@ -1,302 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.util;
-
-import java.util.ArrayList;
-import java.util.List;
-import javax.annotation.Nonnull;
-import org.rosi_project.model_sync.model_join.representation.core.OCLConstraint;
-import org.rosi_project.model_sync.model_join.representation.grammar.JoinExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.KeepExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.NaturalJoinExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.OuterJoinExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.OuterJoinExpression.JoinDirection;
-import org.rosi_project.model_sync.model_join.representation.core.ClassResource;
-import org.rosi_project.model_sync.model_join.representation.grammar.ThetaJoinExpression;
-
-/**
- * The {@code JoinFactory} should be used as the main facility to create new {@link JoinExpression}
- * instances. It supports instantiation for all subclasses and provides a fluid and natural
- * interface to set them up.
- *
- * @author Rico Bergmann
- */
-public class JoinFactory {
-
-  /**
-   * Starts the construction process for a new join.
-   */
-  @Nonnull
-  public static JoinFactory createNew() {
-    return new JoinFactory();
-  }
-
-  private JoinFactory() {
-    // pass
-  }
-
-  /**
-   * Constructs a new {@link OuterJoinExpression outer join}
-   */
-  @Nonnull
-  public OuterJoinBuilder outer() {
-    return new OuterJoinBuilder();
-  }
-
-  /**
-   * Constructs a new {@link NaturalJoinExpression natural join}.
-   */
-  @Nonnull
-  public NaturalJoinBuilder natural() {
-    return new NaturalJoinBuilder();
-  }
-
-  /**
-   * Constructs a new {@link ThetaJoinExpression theta join}.
-   */
-  @Nonnull
-  public ThetaJoinBuilder theta() {
-    return new ThetaJoinBuilder();
-  }
-
-  /**
-   * This is the base for all actual join builders and contains the fields that have to be present
-   * in each join. Consult the documentation of the {@link JoinExpression} class for details on
-   * those fields.
-   * <p>
-   * Despite all builders working very similarly, they may not be refactored to have more logic
-   * provided through this class due to limitations of the Java language.
-   *
-   * @see JoinExpression
-   */
-  public static abstract class AbstractJoinBuilder {
-    protected ClassResource left;
-    protected ClassResource right;
-    protected ClassResource target;
-    protected List<KeepExpression> keeps = new ArrayList<>();
-  }
-
-  /**
-   * The {@code OuterJoinBuilder} takes care of setting up new {@link OuterJoinExpression}
-   * instances.
-   *
-   * @see OuterJoinExpression
-   */
-  public static class OuterJoinBuilder extends AbstractJoinBuilder {
-
-    private OuterJoinExpression.JoinDirection direction;
-
-    /**
-     * Default constructor.
-     * <p>
-     * {@code private} to prevent direct instantiation.
-     */
-    private OuterJoinBuilder() {
-      // pass
-    }
-
-    /**
-     * Configures the join to use the right source model as the primary one.
-     */
-    @Nonnull
-    public OuterJoinBuilder rightOuter() {
-      direction = JoinDirection.RIGHT;
-      return this;
-    }
-
-    /**
-     * Configures the join to use the left source model as the primary one.
-     */
-    @Nonnull
-    public OuterJoinBuilder leftOuter() {
-      direction = JoinDirection.LEFT;
-      return this;
-    }
-
-    /**
-     * Specifies the left source.
-     */
-    @Nonnull
-    public OuterJoinBuilder join(@Nonnull ClassResource left) {
-      this.left = left;
-      return this;
-    }
-
-    /**
-     * Specifies the right source.
-     */
-    @Nonnull
-    public OuterJoinBuilder with(@Nonnull ClassResource right) {
-      this.right = right;
-      return this;
-    }
-
-    /**
-     * Specifies the name of the resulting class.
-     */
-    @Nonnull
-    public OuterJoinBuilder as(@Nonnull ClassResource target) {
-      this.target = target;
-      return this;
-    }
-
-    /**
-     * Specifies a field that should be contained in the resulting view.
-     */
-    @Nonnull
-    public OuterJoinBuilder keep(@Nonnull KeepExpression keep) {
-      this.keeps.add(keep);
-      return this;
-    }
-
-    /**
-     * Finishes the construction process and provides the resulting {@code join}.
-     */
-    @Nonnull
-    public OuterJoinExpression done() {
-      return new OuterJoinExpression(left, right, target, direction, keeps);
-    }
-  }
-
-  /**
-   * The {@code NaturalJoinBuilder} takes care of setting up new {@link NaturalJoinExpression}
-   * instances.
-   *
-   * @see NaturalJoinExpression
-   */
-  public static class NaturalJoinBuilder extends AbstractJoinBuilder {
-
-    /**
-     * Default constructor.
-     * <p>
-     * {@code private} to prevent direct instantiation.
-     */
-    private NaturalJoinBuilder() {
-      // pass
-    }
-
-    /**
-     * Specifies the left source.
-     */
-    @Nonnull
-    public NaturalJoinBuilder join(@Nonnull ClassResource left) {
-      this.left = left;
-      return this;
-    }
-
-    /**
-     * Specifies the right source.
-     */
-    @Nonnull
-    public NaturalJoinBuilder with(@Nonnull ClassResource right) {
-      this.right = right;
-      return this;
-    }
-
-    /**
-     * Specifies the name of the resulting class.
-     */
-    @Nonnull
-    public NaturalJoinBuilder as(@Nonnull ClassResource target) {
-      this.target = target;
-      return this;
-    }
-
-    /**
-     * Specifies a field that should be contained in the resulting view.
-     */
-    @Nonnull
-    public NaturalJoinBuilder keep(@Nonnull KeepExpression keep) {
-      this.keeps.add(keep);
-      return this;
-    }
-
-    /**
-     * Finishes the construction process and provides the resulting {@code join}.
-     */
-    @Nonnull
-    public NaturalJoinExpression done() {
-      return new NaturalJoinExpression(left, right, target, keeps);
-    }
-  }
-
-  /**
-   * The {@code ThetaJoinBuilder} takes care of setting up new {@link ThetaJoinExpression}
-   * instances.
-   *
-   * @see ThetaJoinExpression
-   */
-  public static class ThetaJoinBuilder extends AbstractJoinBuilder {
-
-    private OCLConstraint condition;
-
-    /**
-     * Default constructor.
-     * <p>
-     * {@code private} to prevent direct instantiation.
-     */
-    private ThetaJoinBuilder() {
-      // pass
-    }
-
-    /**
-     * Specifies the left source.
-     */
-    @Nonnull
-    public ThetaJoinBuilder join(@Nonnull ClassResource left) {
-      this.left = left;
-      return this;
-    }
-
-    /**
-     * Specifies the right source.
-     */
-    @Nonnull
-    public ThetaJoinBuilder with(@Nonnull ClassResource right) {
-      this.right = right;
-      return this;
-    }
-
-    /**
-     * Specifies the name of the resulting class.
-     */
-    @Nonnull
-    public ThetaJoinBuilder as(@Nonnull ClassResource target) {
-      this.target = target;
-      return this;
-    }
-
-    /**
-     * Specifies the join condition.
-     */
-    @Nonnull
-    public ThetaJoinBuilder where(@Nonnull OCLConstraint condition) {
-      this.condition = condition;
-      return this;
-    }
-
-    /**
-     * Specifies the join condition.
-     */
-    @Nonnull
-    public ThetaJoinBuilder where(@Nonnull String oclCondition) {
-      return where(OCLConstraint.of(oclCondition));
-    }
-
-    /**
-     * Specifies a field that should be contained in the resulting view.
-     */
-    @Nonnull
-    public ThetaJoinBuilder keep(@Nonnull KeepExpression keep) {
-      this.keeps.add(keep);
-      return this;
-    }
-
-    /**
-     * Finishes the construction process and provides the resulting {@code join}.
-     */
-    @Nonnull
-    public ThetaJoinExpression done() {
-      return new ThetaJoinExpression(left, right, target, condition, keeps);
-    }
-  }
-
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/util/ModelJoinBuilder.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/util/ModelJoinBuilder.java
deleted file mode 100644
index c92b525cc3cab941a9524c8b396b0de39958d25c..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/util/ModelJoinBuilder.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.util;
-
-import java.util.LinkedList;
-import java.util.List;
-import javax.annotation.Nonnull;
-import org.rosi_project.model_sync.model_join.representation.core.AttributePath;
-import org.rosi_project.model_sync.model_join.representation.core.ClassResource;
-import org.rosi_project.model_sync.model_join.representation.grammar.JoinExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.KeepAttributesExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.KeepReferenceExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.KeepReferenceExpression.KeepReferenceBuilder;
-import org.rosi_project.model_sync.model_join.representation.grammar.KeepSuperTypeExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.KeepSuperTypeExpression.KeepSuperTypeBuilder;
-import org.rosi_project.model_sync.model_join.representation.grammar.ModelJoinExpression;
-import org.rosi_project.model_sync.model_join.representation.util.JoinFactory.NaturalJoinBuilder;
-import org.rosi_project.model_sync.model_join.representation.util.JoinFactory.ThetaJoinBuilder;
-
-/**
- * The {@code ModelJoinBuilder} provides a nice and fluent way of creating new {@code ModelJoin}
- * instances.
- *
- * @author Rico Bergmann
- */
-public class ModelJoinBuilder {
-
-  public static ThetaJoinBuilder thetaJoin() {
-    return JoinFactory.createNew().theta();
-  }
-  
-  public static NaturalJoinBuilder naturalJoin() {
-	  return JoinFactory.createNew().natural();
-  }
-
-  public static KeepAttributesExpression attributes(AttributePath firstAttribute, AttributePath... moreAttributes) {
-    return KeepAttributesExpression.keepAttributes(firstAttribute, moreAttributes);
-  }
-
-  public static KeepReferenceBuilder outgoing(AttributePath attr) {
-    return KeepReferenceExpression.keep().outgoing(attr);
-  }
-
-  public static KeepSuperTypeBuilder supertype(ClassResource supertype) {
-    return KeepSuperTypeExpression.keep().supertype(supertype);
-  }
-
-  /**
-   * Starts the construction process for a new {@link ModelJoinExpression}.
-   */
-  @Nonnull
-  public static ModelJoinBuilder createNewModelJoin() {
-    return new ModelJoinBuilder();
-  }
-
-  private List<JoinExpression> joinBuffer = new LinkedList<>();
-
-  /**
-   * Full/default constructor.
-   */
-  private ModelJoinBuilder() {
-    // pass
-  }
-
-  /**
-   * Extends the current {@code ModelJoin} by another join.
-   */
-  @Nonnull
-  public ModelJoinBuilder add(@Nonnull JoinExpression join) {
-    joinBuffer.add(join);
-    return this;
-  }
-
-  /**
-   * Finishes the construction process and provides the resulting {@code ModelJoin}.
-   */
-  @Nonnull
-  public ModelJoinExpression build() {
-    return new ModelJoinExpression(joinBuffer);
-  }
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/util/Nothing.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/util/Nothing.java
deleted file mode 100644
index 6f4ddf4e0686a58f691c788bf2c71a5bcabde1b4..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/util/Nothing.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.util;
-
-public final class Nothing {
-
-  public static Nothing __() {
-    return new Nothing();
-  }
-
-  private Nothing() {};
-
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/util/Pair.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/util/Pair.java
deleted file mode 100644
index 8cfb469171b91948577ec7a0016ecba646cd7029..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/util/Pair.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.util;
-
-import java.util.Objects;
-
-public class Pair<F, S> {
-
-  public static <F, S> Pair<F, S> of(F first, S second) {
-    return new Pair<F, S>(first, second);
-  }
-
-  private final F first;
-  private final S second;
-
-  public Pair(F first, S second) {
-    this.first = first;
-    this.second = second;
-  }
-
-  public F getFirst() {
-    return first;
-  }
-
-  public S getSecond() {
-    return second;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (!(o instanceof Pair)) {
-      return false;
-    }
-    Pair<?, ?> pair = (Pair<?, ?>) o;
-    return Objects.equals(first, pair.first) &&
-        Objects.equals(second, pair.second);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(first, second);
-  }
-
-  public String toString() {
-    return "(" + first + ", " + second + ")";
-  }
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/writer/FileBasedModelJoinWriter.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/writer/FileBasedModelJoinWriter.java
deleted file mode 100644
index e9cc804f59a7bbf116cfc0916c61381b322e9401..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/writer/FileBasedModelJoinWriter.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.writer;
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.StandardOpenOption;
-import javax.annotation.Nonnull;
-import org.rosi_project.model_sync.model_join.representation.grammar.ModelJoinExpression;
-
-/**
- * The {@code FileBasedModelJoinWriter} outputs a {@link ModelJoinExpression model join description}
- * onto the File System.
- *
- * @author Rico Bergmann
- */
-public class FileBasedModelJoinWriter implements ModelJoinWritingService<Boolean> {
-
-  private final File outputFile;
-  private final StringBasedModelJoinWriter toStringWriter;
-
-  /**
-   * Full constructor.
-   *
-   * @param outputFile the file to write to
-   */
-  public FileBasedModelJoinWriter(@Nonnull File outputFile) {
-    this.outputFile = outputFile;
-    this.toStringWriter = StringBasedModelJoinWriter.withNewlines();
-  }
-
-  /**
-   * Writes the given description to the {@code outputFile}.
-   *
-   * @return whether the file was successfully written
-   */
-  @Override
-  public Boolean write(@Nonnull ModelJoinExpression modelJoin) {
-    try (BufferedWriter writer = Files.newBufferedWriter(
-        outputFile.toPath(),
-        StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING)) {
-
-      String modelJoinTextRepresentation = toStringWriter.write(modelJoin);
-      writer.write(modelJoinTextRepresentation);
-
-      return true;
-    } catch (IOException ioe) {
-      return false;
-    }
-  }
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/writer/ModelJoinWriter.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/writer/ModelJoinWriter.java
deleted file mode 100644
index 96d3434153904743c2f634cb890be8ba823e32a8..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/writer/ModelJoinWriter.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.writer;
-
-import java.io.File;
-import javax.annotation.Nonnull;
-import org.rosi_project.model_sync.model_join.representation.grammar.ModelJoinExpression;
-
-/**
- * The {@code ModelJoinWriter} acts as an entry point to write and or transform {@link
- * ModelJoinExpression model join descriptions} to various representations.
- *
- * @author Rico Bergmann
- */
-public class ModelJoinWriter {
-
-  private static final StringBasedModelJoinWriter stringWriter = StringBasedModelJoinWriter
-      .createDefault();
-
-  /**
-   * Converts a whole model join description to a single {@code String}.
-   * <p>
-   * This {@code String} is primarily intended to be human-readable and does not focus in being easy
-   * to reuse for further purposes.
-   */
-  public static String writeToString(@Nonnull ModelJoinExpression modelJoin) {
-    return stringWriter.write(modelJoin);
-  }
-
-  /**
-   * Outputs a whole model join description to a single file.
-   * <p>
-   * The resulting file is intended to be both human-readable as well as to be parsed by further
-   * applications.
-   *
-   * @return whether the expression was written successfully.
-   */
-  public static boolean writeToFile(
-      @Nonnull File outputFile,
-      @Nonnull ModelJoinExpression modelJoin) {
-    return new FileBasedModelJoinWriter(outputFile).write(modelJoin);
-  }
-
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/writer/ModelJoinWritingService.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/writer/ModelJoinWritingService.java
deleted file mode 100644
index 4f89772ac9e62bef6ad2952892b60862cfcd6510..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/writer/ModelJoinWritingService.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.writer;
-
-import javax.annotation.Nonnull;
-import org.rosi_project.model_sync.model_join.representation.grammar.ModelJoinExpression;
-
-/**
- * A {@code ModelJoinWritingService} transforms a {@link ModelJoinExpression model join description}
- * into some different representation.
- *
- * @author Rico Bergmann
- */
-public interface ModelJoinWritingService<T> {
-
-  /**
-   * Performs the transformation. The result of this method depends on the actual details of the
-   * writing service and should be documented there.
-   */
-  T write(@Nonnull ModelJoinExpression modelJoin);
-
-}
diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/writer/StringBasedModelJoinWriter.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/writer/StringBasedModelJoinWriter.java
deleted file mode 100644
index 8281979371398a408c082622e8d6d10fa37de98d..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/model_join/representation/writer/StringBasedModelJoinWriter.java
+++ /dev/null
@@ -1,160 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.writer;
-
-import java.util.StringJoiner;
-import javax.annotation.Nonnull;
-import org.rosi_project.model_sync.model_join.representation.grammar.CompoundKeepExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.JoinExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.KeepAggregateExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.KeepAttributesExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.KeepCalculatedExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.KeepExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.KeepReferenceExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.KeepSubTypeExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.KeepSuperTypeExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.ModelJoinExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.NaturalJoinExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.OuterJoinExpression;
-import org.rosi_project.model_sync.model_join.representation.grammar.ThetaJoinExpression;
-import org.rosi_project.model_sync.model_join.representation.util.Functional;
-import org.rosi_project.model_sync.model_join.representation.util.Nothing;
-
-/**
- * The {@code StringBasedModelJoinWriter} transforms a {@link ModelJoinExpression model join description}
- * to a single {@code String}.
- *
- * @author Rico Bergmann
- */
-class StringBasedModelJoinWriter implements ModelJoinWritingService<String> {
-
-  private static final String NEWLINE_DELIM = "\n";
-  private static final String EMPTY_DELIM = " ";
-  private static final String DEFAULT_INDENTATION = "  ";
-
-  static StringBasedModelJoinWriter createDefault() {
-    return new StringBasedModelJoinWriter(false);
-  }
-
-  static StringBasedModelJoinWriter withNewlines() {
-    return new StringBasedModelJoinWriter(true);
-  }
-
-  private final String delimiter;
-  private final boolean useNewlineDelimiters;
-
-  private String currentIndentation = "";
-
-  private StringBasedModelJoinWriter(boolean useNewlinesDelimiters) {
-    if (useNewlinesDelimiters) {
-      this.delimiter = NEWLINE_DELIM;
-    } else {
-      this.delimiter = EMPTY_DELIM;
-    }
-    this.useNewlineDelimiters = useNewlinesDelimiters;
-  }
-
-  @Override
-  public String write(@Nonnull ModelJoinExpression modelJoin) {
-    StringJoiner joiner = new StringJoiner(delimiter + delimiter);
-
-    modelJoin.getJoins().forEach(
-        joinStatement -> joiner.merge(writeJoin(joinStatement))
-    );
-
-    return joiner.toString();
-  }
-
-  private StringJoiner writeJoin(@Nonnull JoinExpression join) {
-    StringJoiner joiner = new StringJoiner(" ");
-
-    String joinHeader = Functional.<String>match(join)
-        .caseOf(ThetaJoinExpression.class, "theta join")
-        .caseOf(NaturalJoinExpression.class, "natural join")
-        .caseOf(OuterJoinExpression.class, outerJoin -> {
-          switch (outerJoin.getDirection()) {
-            case LEFT:
-              return "left outer join";
-            case RIGHT:
-              return "right outer join";
-            default:
-              throw new AssertionError(outerJoin.getDirection());
-          }
-        })
-        .runOrThrow();
-    joiner.add(String.format(currentIndentation + "%s %s with %s as %s", joinHeader, join.getLeft(), join.getRight(), join.getTarget()));
-    Functional.<Nothing>match(join)
-        .caseOf(ThetaJoinExpression.class, thetaJoin -> {
-          joiner.add("where").add(thetaJoin.getCondition().toString());
-          return Nothing.__();
-        })
-        .defaultCase(Nothing.__())
-        .runOrThrow();
-
-    joiner.add("{\n");
-    increaseIndentationIfNecessary();
-    join.getKeeps().forEach(keep -> joiner.add(currentIndentation + writeKeep(keep) + delimiter));
-    decreaseIndentationIfNecessary();
-    joiner.add(currentIndentation + "}");
-
-    return joiner;
-  }
-
-  private String writeKeep(KeepExpression keep) {
-
-    return Functional.<String>match(keep)
-        .caseOf(KeepAttributesExpression.class, keepAttributes -> {
-          StringJoiner attributesJoiner = new StringJoiner(", ");
-          keepAttributes.getAttributes().forEach(attr -> attributesJoiner.add(attr.toString()));
-          return "keep attributes " + attributesJoiner;
-        })
-        .caseOf(KeepCalculatedExpression.class, keepCalculated ->
-            "keep calculated attribute "
-                + keepCalculated.getCalculationRule()
-                + " as " + keepCalculated.getTarget())
-        .caseOf(KeepAggregateExpression.class, keepAggregate ->
-            String.format("keep aggregate %s(%s) over %s as %s",
-                keepAggregate.getAggregation().name().toLowerCase(),
-                keepAggregate.getAggregatedAttribute(),
-                keepAggregate.getSource(), keepAggregate.getTarget())
-            )
-        .caseOf(KeepReferenceExpression.class, keepRef -> {
-          String header = String.format("keep %s %s as type %s {" + delimiter, keepRef.getReferenceDirection().name().toLowerCase(), keepRef.getAttribute(), keepRef.getTarget());
-          return writeCompound(keepRef, header);
-        })
-        .caseOf(KeepSubTypeExpression.class, keepSubtype -> {
-          String header = String.format("keep subtype %s as type %s {" + delimiter, keepSubtype.getType(), keepSubtype.getTarget());
-          return writeCompound(keepSubtype, header);
-        })
-        .caseOf(KeepSuperTypeExpression.class, keepSupertype -> {
-          String header = String.format("keep supertype %s as type %s {" + delimiter, keepSupertype.getType(), keepSupertype.getTarget());
-          return writeCompound(keepSupertype, header);
-        })
-        .runOrThrow();
-
-  }
-
-  private String writeCompound(CompoundKeepExpression compoundKeep, String header) {
-    StringJoiner refJoiner = new StringJoiner(" ");
-
-    refJoiner.add(header);
-    increaseIndentationIfNecessary();
-    compoundKeep.getKeeps().forEach(keep -> refJoiner.add(currentIndentation + writeKeep(keep) + delimiter));
-    decreaseIndentationIfNecessary();
-    refJoiner.add(currentIndentation + "}");
-
-    return refJoiner.toString();
-  }
-
-  private void increaseIndentationIfNecessary() {
-    if (useNewlineDelimiters) {
-      currentIndentation += DEFAULT_INDENTATION;
-    }
-  }
-
-  private  void decreaseIndentationIfNecessary() {
-    if (useNewlineDelimiters) {
-      int deletionIdx = currentIndentation.lastIndexOf(DEFAULT_INDENTATION);
-      currentIndentation = currentIndentation.substring(0, deletionIdx);
-    }
-  }
-
-}
diff --git a/src/main/java/org/rosi_project/model_sync/modelrepresentation/ModelJoinCreation.java b/src/main/java/org/rosi_project/model_sync/modelrepresentation/ModelJoinCreation.java
deleted file mode 100644
index 44fa819a32695600f414d3adb075e0d8c4411cb6..0000000000000000000000000000000000000000
--- a/src/main/java/org/rosi_project/model_sync/modelrepresentation/ModelJoinCreation.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package org.rosi_project.model_sync.modelrepresentation;
-
-import static org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder.attributes;
-import static org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder.outgoing;
-import static org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder.supertype;
-import static org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder.thetaJoin;
-import static org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder.naturalJoin;
-
-import java.io.File;
-
-import org.rosi_project.model_sync.model_join.representation.core.AttributePath;
-import org.rosi_project.model_sync.model_join.representation.core.ClassResource;
-import org.rosi_project.model_sync.model_join.representation.grammar.ModelJoinExpression;
-import org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder;
-import org.rosi_project.model_sync.model_join.representation.writer.*;
-
-public class ModelJoinCreation {
-
-	public static void main(String[] args) {
-		/*ClassResource person = ClassResource.fromQualifiedName("contact.Person");
-		ClassResource employee = ClassResource.fromQualifiedName("company.Employee");
-		AttributePath dateOfBirth = AttributePath.from(person, "dateOfBirth");
-
-		ModelJoinExpression mj = ModelJoinBuilder.createNewModelJoin()
-		  .add(JoinFactory.createNew()
-		    .natural()
-		    .join(person)
-		    .with(employee)
-		    .as(ClassResource.fromQualifiedName("unified.Person"))
-		    .keep(KeepAttributesExpression
-		      .keepAttributes(dateOfBirth))
-		    .done()
-		  ).build();
-		System.out.println(mj);
-		for (JoinExpression j: mj.getJoins()) {
-			System.out.println(j);
-			for (KeepExpression k: j.getKeeps()) {
-				System.out.println(k);
-			}
-		}*/
-		
-		ClassResource library = ClassResource.from("lib", "Library");
-	    ClassResource employee = ClassResource.from("lib", "Employee");
-	    ClassResource person = ClassResource.from("lib", "Person");
-	    
-	    //ClassResource jointargetMovie = ClassResource.from("jointarget", "Movie");
-	    //ClassResource jointargetVote = ClassResource.from("jointarget", "Vote");
-	    //ClassResource jointargetMediaItem = ClassResource.from("jointarget", "MediaItem");
-
-	    AttributePath libraryName = AttributePath.from(library, "name");
-	    AttributePath libraryEmployees = AttributePath.from(library, "employees");
-	    AttributePath employeeSalary = AttributePath.from(employee, "salary");
-	    AttributePath employeeManager = AttributePath.from(employee, "manager");
-	    AttributePath personName = AttributePath.from(person, "name");
-	    
-	    ModelJoinExpression mjManager = ModelJoinBuilder.createNewModelJoin()
-		        .add(naturalJoin()
-		            .join(employee)
-		            .with(employee)
-		            .as(employee)
-		            .keep(attributes(employeeSalary))
-		            .keep(outgoing(employeeManager)
-		                .as(employee)
-		                .buildExpression()
-		            )
-		            .keep(supertype(person)
-			                .as(person)
-			                .keep(attributes(personName))
-			                .buildExpression()
-			        )
-		            .done())
-		        .build();
-	    
-		ModelJoinExpression mjComplete = ModelJoinBuilder.createNewModelJoin()
-		        .add(naturalJoin()
-		            .join(library)
-		            .with(library)
-		            .as(library)
-		            .keep(attributes(libraryName))
-		            .keep(outgoing(libraryEmployees)
-		                .as(employee)
-		                .keep(attributes(employeeSalary))
-		                .keep(outgoing(employeeManager)
-		                		.as(employee)
-		                		.buildExpression()
-		                )
-		                .keep(supertype(person)
-				                .as(person)
-				                .keep(attributes(personName))
-				                .buildExpression()
-				        )
-		                .buildExpression()
-		            )
-		            .done())
-		        .build();
-		
-		ModelJoinExpression mjSimple = ModelJoinBuilder.createNewModelJoin()
-		        .add(naturalJoin()
-		            .join(library)
-		            .with(library)
-		            .as(library)
-		            .keep(attributes(libraryName))
-		            .keep(outgoing(libraryEmployees)
-		                .as(employee)
-		                .keep(attributes(employeeSalary))
-		                .keep(supertype(person)
-				                .as(person)
-				                .keep(attributes(personName))
-				                .buildExpression()
-				        )
-		                .buildExpression()
-		            )
-		            .done())
-		        .build();
-		
-		File fileComplete = new File("libraryComplete.modeljoin");
-		File fileSimple = new File("librarySimple.modeljoin");
-		File fileManager = new File("manager.modeljoin");
-	    //registerCreatedFile(outputFile);
-
-	    FileBasedModelJoinWriter writerComplete = new FileBasedModelJoinWriter(fileComplete);
-	    writerComplete.write(mjComplete);
-	    
-	    FileBasedModelJoinWriter writerSimple = new FileBasedModelJoinWriter(fileSimple);
-	    writerSimple.write(mjSimple);
-	    
-	    FileBasedModelJoinWriter writerManager = new FileBasedModelJoinWriter(fileManager);
-	    writerManager.write(mjManager);
-	}
-
-}
diff --git a/src/main/scala/org/rosi_project/model_sync/generator/sync/PredefRsumTypes.scala b/src/main/scala/org/rosi_project/model_sync/generator/sync/PredefRsumTypes.scala
index 994c2f696eb05a504ec79808debb8a09f1247499..c37d1df3cde8ae63007e17a6216c3937a9a7f848 100644
--- a/src/main/scala/org/rosi_project/model_sync/generator/sync/PredefRsumTypes.scala
+++ b/src/main/scala/org/rosi_project/model_sync/generator/sync/PredefRsumTypes.scala
@@ -37,10 +37,10 @@ object PredefRsumTypes {
   private val QUERY_HELPER_CLASS = classOf[QueryHelper]
   val         QUERY_HELPER_STYPE = SType(QUERY_HELPER_CLASS.getSimpleName, QUERY_HELPER_CLASS.getPackage.getName) 
   
-  private val IQUERY_VIEW_COMPARTMENT_CLASS = classOf[IQueryViewCompartment]
+  private val IQUERY_VIEW_COMPARTMENT_CLASS = classOf[QueryFactory]
   val         IQUERY_VIEW_COMPARTMENT_STYPE = SType(IQUERY_VIEW_COMPARTMENT_CLASS.getSimpleName, IQUERY_VIEW_COMPARTMENT_CLASS.getPackage.getName) 
   
-  private val AQUERY_VIEW_ROLE_CLASS = classOf[IQueryViewCompartment#AQueryViewRole]
+  private val AQUERY_VIEW_ROLE_CLASS = classOf[QueryFactory#QueryFactoryElement]
   val         AQUERY_VIEW_ROLE_STYPE = SType(AQUERY_VIEW_ROLE_CLASS.getSimpleName) //, AQUERY_VIEW_ROLE_CLASS.getPackage.getName) 
 
   //RELATIONAL COMPARTMENT TYPES
diff --git a/src/test/java/org/rosi_project/model_sync/model_join/representation/writer/FileBasedModelJoinWriterAcceptanceTests.java b/src/test/java/org/rosi_project/model_sync/model_join/representation/writer/FileBasedModelJoinWriterAcceptanceTests.java
deleted file mode 100644
index 115556369bdefdd7850579d6c81c04ceb348390f..0000000000000000000000000000000000000000
--- a/src/test/java/org/rosi_project/model_sync/model_join/representation/writer/FileBasedModelJoinWriterAcceptanceTests.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.writer;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.logging.Logger;
-import java.util.stream.Collectors;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.Test;
-import org.rosi_project.model_sync.model_join.representation.writer.TestedModels.Listing2;
-
-class FileBasedModelJoinWriterAcceptanceTests {
-
-  private static final Logger log = Logger.getLogger(FileBasedModelJoinWriterAcceptanceTests.class.getSimpleName());
-
-  private List<File> createdFiles = new ArrayList<>();
-
-  @AfterEach
-  void tearDown() {
-    createdFiles.forEach(file -> {
-      boolean result = file.delete();
-      log.info(String.format("Deleting file %s, successfull=%s", file, result));
-    });
-    createdFiles.clear();
-  }
-
-  /**
-   * Depends on {@link StringBasedModelJoinWriterAcceptanceTests#writeProducesListing2FromTechnicalReport()}
-   */
-  @Test
-  void writeProducesListing2FromTechnicalReport() {
-    File outputFile = new File("listing2.modeljoin");
-    registerCreatedFile(outputFile);
-
-    FileBasedModelJoinWriter writer = new FileBasedModelJoinWriter(outputFile);
-    writer.write(Listing2.asModelJoin);
-
-    logFileContent(outputFile);
-
-    String expectedContent = StringBasedModelJoinWriter.withNewlines().write(Listing2.asModelJoin);
-    assertThat(outputFile).exists();
-    assertThat(outputFile).hasContent(expectedContent);
-  }
-
-  private void registerCreatedFile(File newFile) {
-    createdFiles.add(newFile);
-    log.info(String.format("Created new file %s", newFile));
-  }
-
-  private void logFileContent(File file) {
-    try {
-      String contents = Files.lines(file.toPath()).collect(Collectors.joining());
-      log.info(String.format("Content of file %s:", file));
-      log.info(contents);
-    } catch (IOException e) {
-      log.severe(String.format("Could not read file %s", file));
-    }
-  }
-
-}
diff --git a/src/test/java/org/rosi_project/model_sync/model_join/representation/writer/StringBasedModelJoinWriterAcceptanceTests.java b/src/test/java/org/rosi_project/model_sync/model_join/representation/writer/StringBasedModelJoinWriterAcceptanceTests.java
deleted file mode 100644
index 716d8d54e9644a7c9eaa2e0f0c6e9e09d8c9e474..0000000000000000000000000000000000000000
--- a/src/test/java/org/rosi_project/model_sync/model_join/representation/writer/StringBasedModelJoinWriterAcceptanceTests.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.writer;
-
-import static org.assertj.core.api.Assertions.*;
-
-import java.util.logging.Logger;
-import org.junit.jupiter.api.Test;
-import org.junit.platform.runner.JUnitPlatform;
-import org.junit.runner.RunWith;
-import org.rosi_project.model_sync.model_join.representation.writer.TestedModels.Listing2;
-
-class StringBasedModelJoinWriterAcceptanceTests {
-
-  private static final Logger log = Logger.getLogger(StringBasedModelJoinWriterAcceptanceTests.class.getSimpleName());
-
-  /**
-   * @see TestedModels
-   */
-  @Test
-  void writeProducesListing2FromTechnicalReport() {
-    StringBasedModelJoinWriter writer = StringBasedModelJoinWriter.withNewlines();
-    String writerOutput = writer.write(Listing2.asModelJoin);
-
-    log.info("Writer output:");
-    log.info(writerOutput);
-
-    String sanitizedWriterOutput = sanitize(writerOutput);
-
-    String expectedOutput = sanitize(Listing2.asString);
-
-    // Although AssertJ provides an isEqualToIgnoringWhitespace as well as an
-    // isEqualToIgnoringNewline method, there's none that ignores both. Thus we reside to manual
-    // sanitization
-    assertThat(sanitizedWriterOutput).isEqualTo(expectedOutput);
-  }
-
-  private String sanitize(String rawModelJoin) {
-    return rawModelJoin.replaceAll("\\s", "");
-  }
-}
diff --git a/src/test/java/org/rosi_project/model_sync/model_join/representation/writer/TestedModels.java b/src/test/java/org/rosi_project/model_sync/model_join/representation/writer/TestedModels.java
deleted file mode 100644
index 12ab7c144319e4a5a33174852cf402f2e22e644f..0000000000000000000000000000000000000000
--- a/src/test/java/org/rosi_project/model_sync/model_join/representation/writer/TestedModels.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package org.rosi_project.model_sync.model_join.representation.writer;
-
-import static org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder.attributes;
-import static org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder.outgoing;
-import static org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder.supertype;
-import static org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder.thetaJoin;
-
-import org.rosi_project.model_sync.model_join.representation.core.AttributePath;
-import org.rosi_project.model_sync.model_join.representation.core.ClassResource;
-import org.rosi_project.model_sync.model_join.representation.grammar.ModelJoinExpression;
-import org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder;
-
-class TestedModels {
-
-  /*
-   * The technical report which forms the basis of the tests here is
-   *
-   * Burger, E. et Al.: "ModelJoin - A Textual Domain-Specific Language for the Combination of
-   *    Heterogeneous Models"; Karslruhe Institute of Technololgy 2014
-   */
-
-  static class Listing2 {
-    static final ClassResource imdbFilm = ClassResource.from("imdb", "Film");
-    static final ClassResource libraryVideoCassette = ClassResource.from("library", "VideoCassette");
-    static final ClassResource libraryAudioVisualItem = ClassResource.from("library", "AudioVisualItem");
-    static final ClassResource jointargetMovie = ClassResource.from("jointarget", "Movie");
-    static final ClassResource jointargetVote = ClassResource.from("jointarget", "Vote");
-    static final ClassResource jointargetMediaItem = ClassResource.from("jointarget", "MediaItem");
-
-    static final AttributePath imdbFilmYear = AttributePath.from(imdbFilm, "year");
-    static final AttributePath imdbFilmVotes = AttributePath.from(imdbFilm, "votes");
-    static final AttributePath imdbVoteScore = AttributePath.from("imdb.Vote", "score");
-    static final AttributePath libraryAudioVisualItemMinutesLength = AttributePath.from(libraryAudioVisualItem, "minutesLength");
-
-    static final ModelJoinExpression asModelJoin = ModelJoinBuilder.createNewModelJoin()
-        .add(thetaJoin()
-            .join(imdbFilm)
-            .with(libraryVideoCassette)
-            .as(jointargetMovie)
-            .where(
-                "library.VideoCassette.cast->forAll (p | imdb.Film.figures->playedBy->exists (a | p.firstname.concat(\" \") .concat(p.lastName) == a.name))")
-            .keep(attributes(imdbFilmYear))
-            .keep(outgoing(imdbFilmVotes)
-                .as(jointargetVote)
-                .keep(attributes(imdbVoteScore))
-                .buildExpression()
-            )
-            .keep(supertype(libraryAudioVisualItem)
-                .as(jointargetMediaItem)
-                .keep(attributes(libraryAudioVisualItemMinutesLength))
-                .buildExpression()
-            )
-            .done())
-        .build();
-
-    static final String asString = "theta join imdb.Film with library.VideoCassette as jointarget.Movie\n"
-        + "where library.VideoCassette.cast->forAll (p | imdb.Film.figures->playedBy->exists (a | p.\n"
-        + "firstname.concat(\" \") .concat(p.lastName) == a.name)) {\n"
-        + " keep attributes imdb.Film.year\n"
-        + " keep outgoing imdb.Film.votes as type jointarget.Vote {\n"
-        + " keep attributes imdb.Vote.score\n"
-        + "}\n"
-        + "keep supertype library.AudioVisualItem as type jointarget.MediaItem {\n"
-        + " keep attributes library.AudioVisualItem.minutesLength\n"
-        + "}\n"
-        + "}";
-  }
-
-}