diff --git a/assemble-tools.sh b/assemble-tools.sh
new file mode 100755
index 0000000000000000000000000000000000000000..1d27050ac69b68e73bcb9e94bfaa059d31e3d347
--- /dev/null
+++ b/assemble-tools.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+BASE_DIR=$(cd "$(dirname "$0")"; pwd)
+
+rm -rf $BASE_DIR/build/oceandsl-tools
+
+mkdir -p $BASE_DIR/build/oceandsl-tools
+cd $BASE_DIR/build/oceandsl-tools
+
+mkdir bin
+mkdir lib
+
+for I in cmi dar mop mvis sar relabel ; do
+	unzip $BASE_DIR/tools/$I/build/distributions/$I.zip
+	mv $I/lib/* lib/
+	mv $I/bin/* bin/
+	rm -rf $I
+done
+
+cd ..
+tar -cvzpf oceandsl-tools.tgz oceandsl-tools
+
+# end
+
diff --git a/build.gradle b/build.gradle
index 529317d47529a60237fef91842c40ed2e497c276..7681be74b0c4a5fe341787cbe9819063beb2009e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -12,7 +12,6 @@ plugins {
 repositories {
     jcenter()
     mavenCentral()
-    maven { url 'https://jitpack.io' }
 }
 
 subprojects {
@@ -20,20 +19,19 @@ subprojects {
 
 	repositories {
 	    jcenter()
+	    mavenLocal()
 	    mavenCentral()
 	    maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
 	    maven { url "https://oss.sonatype.org/content/repositories/releases/" }
-	    maven { url 'https://jitpack.io' }
 	}
 	
 	dependencies {
-	implementation 'net.kieker-monitoring:kieker:1.16-SNAPSHOT'
-	implementation 'net.sourceforge.teetime:teetime:3.0'
-	implementation 'com.beust:jcommander:1.78'
-    implementation 'ch.qos.logback:logback-classic:1.1.7'
-    implementation 'org.slf4j:slf4j-api:1.7.30'
+        implementation 'net.kieker-monitoring:kieker:1.16-SNAPSHOT'
+        implementation 'net.sourceforge.teetime:teetime:3.1-SNAPSHOT'
+        implementation 'com.beust:jcommander:1.78'
+        implementation 'ch.qos.logback:logback-classic:1.1.7'
+        implementation 'org.slf4j:slf4j-api:1.7.30'
         implementation 'org.codehaus.groovy:groovy-all:3.0.2'
-        implementation 'com.github.MoSimEngine.RefactorLizar:architecture-evaluation:6214cbdfb6'
 	
 	    // Use JUnit test framework
 	    testImplementation 'junit:junit:4.13'
diff --git a/common/build.gradle b/common/build.gradle
index 3f64f91a8eeacdb84f5c98d943f5767e0b39f5c7..602a910fce49dd9f6d3cc9e8f2f481889aa33364 100644
--- a/common/build.gradle
+++ b/common/build.gradle
@@ -81,8 +81,8 @@ signing {
 }
 
 
-javadoc {
-    if(JavaVersion.current().isJava9Compatible()) {
-        options.addBooleanOption('html5', true)
-    }
-}
+//javadoc {
+//    if(JavaVersion.current().isJava9Compatible()) {
+//        options.addBooleanOption('html5', true)
+//    }
+//}
diff --git a/settings.gradle b/settings.gradle
index a8c582445e359c175f980b8397d7d3ad5f29e303..9034a46d36f259531cd5e54b7d9d5fe885c7ed47 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -19,5 +19,6 @@ include 'tools:dar'
 include 'tools:mop'
 include 'tools:mvis'
 include 'tools:cmi'
+include 'tools:relabel'
 
 
diff --git a/tools/cmi/src/main/java/org/oceandsl/tools/cmi/CheckModelIntegrityMain.java b/tools/cmi/src/main/java/org/oceandsl/tools/cmi/CheckModelIntegrityMain.java
index e625995faea3e67eedb30d34d9a6d5648b9b26af..8a9b1885b8a26221beb346b99953ceec9681a22d 100644
--- a/tools/cmi/src/main/java/org/oceandsl/tools/cmi/CheckModelIntegrityMain.java
+++ b/tools/cmi/src/main/java/org/oceandsl/tools/cmi/CheckModelIntegrityMain.java
@@ -75,7 +75,8 @@ public class CheckModelIntegrityMain {
         errors = 0;
         for (final Entry<Class<? extends EObject>, List<Class<? extends EObject>>> modelConfig : CheckModelIntegrityMain
                 .configureModels().entrySet()) {
-            errors += CheckModelIntegrityMain.checkReferences(repository.getModel(modelConfig.getKey()).eAllContents());
+            errors += CheckModelIntegrityMain.checkReferences(modelConfig.getKey(),
+                    repository.getModel(modelConfig.getKey()).eAllContents());
         }
 
         System.out.printf("Missing references %s\n", errors);
@@ -88,9 +89,60 @@ public class CheckModelIntegrityMain {
         }
         System.out.printf("Missing signature %s\n", errors);
 
+        // CheckModelIntegrityMain.checkForDuplicateDeployedOperations(repository.getModel(DeploymentModel.class));
+
         CheckModelIntegrityMain.checkExecutionInvocationIntegrity(repository.getModel(ExecutionModel.class),
                 repository.getModel(DeploymentModel.class));
         CheckModelIntegrityMain.checkExecutionStorageAccessIntegrity(repository.getModel(ExecutionModel.class));
+        CheckModelIntegrityMain.checkForDuplicateInvocations(repository.getModel(ExecutionModel.class));
+    }
+
+//    private static void checkForDuplicateDeployedOperations(final DeploymentModel model) {
+//        for (final DeploymentContext context : model.getDeploymentContexts().values()) {
+//            for (final DeployedComponent component : context.getComponents().values()) {
+//                component.getContainedOperations().keySet()
+//            }
+//        }
+//    }
+
+    private static void checkForDuplicateInvocations(final ExecutionModel model) {
+        System.out.println("Check for duplicate invocations based on DeployedOperation");
+        final Map<DeployedOperation, Map<DeployedOperation, AggregatedInvocation>> map = new HashMap<>();
+        for (final AggregatedInvocation invocation : model.getAggregatedInvocations().values()) {
+            Map<DeployedOperation, AggregatedInvocation> targetMap = map.get(invocation.getSource());
+            if (targetMap == null) {
+                targetMap = new HashMap<>();
+                targetMap.put(invocation.getTarget(), invocation);
+            } else {
+                if (targetMap.get(invocation.getTarget()) != null) {
+                    System.out.printf("Found duplicate %s -> %s\n",
+                            invocation.getSource().getAssemblyOperation().getOperationType().getName(),
+                            invocation.getTarget().getAssemblyOperation().getOperationType().getName());
+                }
+            }
+        }
+
+        System.out.println("Check for duplicate invocations based on DeployedOperation names");
+        final List<String> l = new ArrayList<>();
+        for (final AggregatedInvocation invocation : model.getAggregatedInvocations().values()) {
+            final String m = String.format("%s:%s:%s -> %s:%s:%s",
+                    invocation.getSource().getComponent().getDeploymentContext().getName(),
+                    invocation.getSource().getComponent().getAssemblyComponent().getSignature(),
+                    invocation.getSource().getAssemblyOperation().getOperationType().getSignature(),
+                    invocation.getTarget().getComponent().getDeploymentContext().getName(),
+                    invocation.getTarget().getComponent().getAssemblyComponent().getSignature(),
+                    invocation.getTarget().getAssemblyOperation().getOperationType().getSignature());
+            boolean g = false;
+            for (final String x : l) {
+                if (x.equals(m)) {
+                    System.out.printf("Found duplicate %s\n", m);
+                    g = true;
+                }
+            }
+            if (!g) {
+                l.add(m);
+            }
+        }
     }
 
     private static void checkExecutionInvocationIntegrity(final ExecutionModel model,
@@ -222,7 +274,9 @@ public class CheckModelIntegrityMain {
         return result;
     }
 
-    private static long checkReferences(final TreeIterator<EObject> iterator) {
+    private static long checkReferences(final Class<? extends EObject> modelClass,
+            final TreeIterator<EObject> iterator) {
+        System.out.printf("Model %s\n", modelClass.getName());
         long errorCount = 0;
         while (iterator.hasNext()) {
             final EObject object = iterator.next();
@@ -230,7 +284,8 @@ public class CheckModelIntegrityMain {
             for (final EReference reference : clazz.getEAllReferences()) {
                 final Object referencedObject = object.eGet(reference, true);
                 if (referencedObject == null) {
-                    System.out.printf("Missing referenced object: %s -> %s\n", RepositoryUtils.getName(object),reference.getName());
+                    System.out.printf("Missing referenced object: %s:%s -> %s:%s\n", object.getClass().getSimpleName(),
+                            RepositoryUtils.getName(object), reference.getEType().getName(), reference.getName());
                     errorCount++;
 
                 }
diff --git a/tools/create-architecture-model/src/main/java/org/oceandsl/architecture/model/stages/CountEventsStage.java b/tools/create-architecture-model/src/main/java/org/oceandsl/architecture/model/stages/CountEventsStage.java
index ac3306527ae1013974513fac7e4d3fbe4a64c5a4..ae4f7334de0fd389fec15bc52b2e5974e35b0753 100644
--- a/tools/create-architecture-model/src/main/java/org/oceandsl/architecture/model/stages/CountEventsStage.java
+++ b/tools/create-architecture-model/src/main/java/org/oceandsl/architecture/model/stages/CountEventsStage.java
@@ -15,12 +15,12 @@
  ***************************************************************************/
 package org.oceandsl.architecture.model.stages;
 
-import teetime.stage.basic.AbstractTransformation;
+import teetime.stage.basic.AbstractFilter;
 
 /**
  * Counts all events and hands them to the next filter unchanged. The stage outputs the number of
- * events for every <code>interval</code> event occurrence and on termination. Output is written to
- * info log channel.
+ * events for every <code>numberOfOccurance</code> event occurrence and on termination. Output is
+ * written to info log channel.
  *
  * @param <T>
  *            event type
@@ -28,19 +28,19 @@ import teetime.stage.basic.AbstractTransformation;
  * @author Reiner Jung
  * @since 1.0
  */
-public class CountEventsStage<T> extends AbstractTransformation<T, T> {
+public class CountEventsStage<T> extends AbstractFilter<T> {
 
     private long counter;
-    private final long interval;
+    private final long numberOfOccurance;
 
-    public CountEventsStage(final long interval) {
-        this.interval = interval;
+    public CountEventsStage(final long numberOfOccurance) {
+        this.numberOfOccurance = numberOfOccurance;
     }
 
     @Override
     protected void execute(final T element) throws Exception {
         this.counter++;
-        if ((this.counter % this.interval) == 0) {
+        if (this.counter % this.numberOfOccurance == 0) {
             this.logger.info("Received {} events.", this.counter);
         }
         this.outputPort.send(element);
diff --git a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/ModelRepositoryProducerStage.java b/tools/create-architecture-model/src/main/java/org/oceandsl/architecture/model/stages/ModelRepositoryProducerStage.java
similarity index 96%
rename from tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/ModelRepositoryProducerStage.java
rename to tools/create-architecture-model/src/main/java/org/oceandsl/architecture/model/stages/ModelRepositoryProducerStage.java
index cc047b2bd42943a85521e337d4970078230940c3..8af6c8a8c943de9a34574c8a74ec2d7720bc6ab6 100644
--- a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/ModelRepositoryProducerStage.java
+++ b/tools/create-architecture-model/src/main/java/org/oceandsl/architecture/model/stages/ModelRepositoryProducerStage.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  ***************************************************************************/
-package org.oceandsl.tools.mvis.stages;
+package org.oceandsl.architecture.model.stages;
 
 import java.nio.file.Path;
 
diff --git a/tools/dar/src/main/java/org/oceandsl/tools/dar/DynamicArchitectureRecoveryMain.java b/tools/dar/src/main/java/org/oceandsl/tools/dar/DynamicArchitectureRecoveryMain.java
index 18932360cf51580c574d3fa24654bbc9da057b93..adac2925e74a380037daacb9f52f8a75caeffe81 100644
--- a/tools/dar/src/main/java/org/oceandsl/tools/dar/DynamicArchitectureRecoveryMain.java
+++ b/tools/dar/src/main/java/org/oceandsl/tools/dar/DynamicArchitectureRecoveryMain.java
@@ -57,7 +57,7 @@ public class DynamicArchitectureRecoveryMain extends AbstractService<TeetimeConf
         try {
             this.repository = ArchitectureModelManagementFactory.createModelRepository(
                     this.parameterConfiguration.getExperimentName(),
-                    this.parameterConfiguration.getComponentMapFile() != null);
+                    this.parameterConfiguration.getComponentMapFiles() != null);
 
             return new TeetimeConfiguration(this.logger, this.parameterConfiguration, this.repository);
         } catch (final IOException | ValueConversionErrorException e) {
diff --git a/tools/dar/src/main/java/org/oceandsl/tools/dar/MapBasedSignatureCleaner.java b/tools/dar/src/main/java/org/oceandsl/tools/dar/MapBasedSignatureCleaner.java
index 00a3389b2f9135bfd4377bb8ee9b74355c00c6ed..69ae508e48fd7a23b1c4f4e0f15f19b542898b6b 100644
--- a/tools/dar/src/main/java/org/oceandsl/tools/dar/MapBasedSignatureCleaner.java
+++ b/tools/dar/src/main/java/org/oceandsl/tools/dar/MapBasedSignatureCleaner.java
@@ -21,6 +21,7 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.slf4j.Logger;
@@ -38,24 +39,27 @@ public class MapBasedSignatureCleaner extends AbstractSignatureCleaner {
 
     private final Map<String, String> componentMap = new HashMap<>();
 
-    public MapBasedSignatureCleaner(final Path componentMapFile, final boolean caseInsensitive) throws IOException {
+    public MapBasedSignatureCleaner(final List<Path> componentMapFiles, final boolean caseInsensitive)
+            throws IOException {
         super(caseInsensitive);
-        this.logger.info("Reading map file {}", componentMapFile.toString());
-        final BufferedReader reader = Files.newBufferedReader(componentMapFile);
-        String line;
-        while ((line = reader.readLine()) != null) {
-            final String[] values = line.split(",");
-            if (values.length == 3) {
-                // 0 = component name
-                // 1 = file name
-                // 2 = function name
-                this.componentMap.put(this.convertToLowerCase(this.removeTrailingUnderscore(values[1].trim())),
-                        this.convertToLowerCase(this.removeTrailingUnderscore(values[0].trim())));
-            } else {
-                this.logger.error("Entry incomplete '{}'", line.trim());
+        for (final Path componentMapFile : componentMapFiles) {
+            this.logger.info("Reading map file {}", componentMapFile.toString());
+            final BufferedReader reader = Files.newBufferedReader(componentMapFile);
+            String line;
+            while ((line = reader.readLine()) != null) {
+                final String[] values = line.split(";");
+                if (values.length == 2) {
+                    // 0 = component name
+                    // 1 = file name
+                    // 2 = function name
+                    this.componentMap.put(this.convertToLowerCase(this.removeTrailingUnderscore(values[1].trim())),
+                            this.convertToLowerCase(this.removeTrailingUnderscore(values[0].trim())));
+                } else {
+                    this.logger.error("Entry incomplete '{}'", line.trim());
+                }
             }
+            reader.close();
         }
-        reader.close();
     }
 
     @Override
diff --git a/tools/dar/src/main/java/org/oceandsl/tools/dar/Settings.java b/tools/dar/src/main/java/org/oceandsl/tools/dar/Settings.java
index e22afaba81ea0e8ad9468ee46efe1be210bd2a2e..c73a0d10d7af183c80ab7c18d59baa84478a12e6 100644
--- a/tools/dar/src/main/java/org/oceandsl/tools/dar/Settings.java
+++ b/tools/dar/src/main/java/org/oceandsl/tools/dar/Settings.java
@@ -17,6 +17,7 @@ package org.oceandsl.tools.dar;
 
 import java.io.File;
 import java.nio.file.Path;
+import java.util.List;
 
 import com.beust.jcommander.Parameter;
 import com.beust.jcommander.converters.FileConverter;
@@ -39,8 +40,8 @@ public class Settings {
     private Path outputDirectory;
 
     @Parameter(names = { "-M",
-            "--component-map" }, required = false, converter = PathConverter.class, description = "Component, file and function map file")
-    private Path componentMapFile;
+            "--component-map" }, required = false, variableArity = true, converter = PathConverter.class, description = "Component, file and function map file")
+    private List<Path> componentMapFiles;
 
     @Parameter(names = { "-a",
             "--addrline" }, required = false, converter = FileConverter.class, description = "Location of the addrline tool")
@@ -84,8 +85,8 @@ public class Settings {
         return this.caseInsensitive;
     }
 
-    public Path getComponentMapFile() {
-        return this.componentMapFile;
+    public List<Path> getComponentMapFiles() {
+        return this.componentMapFiles;
     }
 
     public String getExperimentName() {
diff --git a/tools/dar/src/main/java/org/oceandsl/tools/dar/TeetimeConfiguration.java b/tools/dar/src/main/java/org/oceandsl/tools/dar/TeetimeConfiguration.java
index 3885abf8c225eef8d29e1995a124183c827f0a65..0528abacdb54eecd2379ac4dfa6937aaafe43099 100644
--- a/tools/dar/src/main/java/org/oceandsl/tools/dar/TeetimeConfiguration.java
+++ b/tools/dar/src/main/java/org/oceandsl/tools/dar/TeetimeConfiguration.java
@@ -85,9 +85,9 @@ public class TeetimeConfiguration extends Configuration {
         final AbstractSignatureCleaner componentSignatureCleaner;
         final AbstractSignatureCleaner operationSignatureCleaner;
 
-        if (parameterConfiguration.getComponentMapFile() != null) {
+        if (parameterConfiguration.getComponentMapFiles() != null) {
             logger.info("Map based component definition");
-            componentSignatureCleaner = new MapBasedSignatureCleaner(parameterConfiguration.getComponentMapFile(),
+            componentSignatureCleaner = new MapBasedSignatureCleaner(parameterConfiguration.getComponentMapFiles(),
                     parameterConfiguration.getCaseInsensitive());
             operationSignatureCleaner = new MapBasedOperationSignatureCleaner(
                     parameterConfiguration.getCaseInsensitive());
diff --git a/tools/mop/build.gradle b/tools/mop/build.gradle
index 766d37ddd392f5c4e33400d8cacd40c54b9d5af7..be36e854d34b3b6cb93dfe6285164cce436e1017 100644
--- a/tools/mop/build.gradle
+++ b/tools/mop/build.gradle
@@ -31,5 +31,5 @@ dependencies {
 }
 
 application {
-    mainClassName = 'org.oceandsl.tools.ModelOperationMain'
+    mainClassName = 'org.oceandsl.tools.mop.ModelOperationMain'
 }
diff --git a/tools/mop/src/main/java/org/oceandsl/tools/mop/operations/AssemblyModelCloneUtils.java b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/AssemblyModelCloneUtils.java
similarity index 90%
rename from tools/mop/src/main/java/org/oceandsl/tools/mop/operations/AssemblyModelCloneUtils.java
rename to tools/mop/src/main/java/org/oceandsl/tools/mop/merge/AssemblyModelCloneUtils.java
index 6075d787c7db6e923232d938ef40b8d3b2b60354..00319302e9e65397d376485adad9a3d66e17bc9b 100644
--- a/tools/mop/src/main/java/org/oceandsl/tools/mop/operations/AssemblyModelCloneUtils.java
+++ b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/AssemblyModelCloneUtils.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  ***************************************************************************/
-package org.oceandsl.tools.mop.operations;
+package org.oceandsl.tools.mop.merge;
 
 import java.util.Map.Entry;
 
@@ -36,6 +36,11 @@ public final class AssemblyModelCloneUtils {
         final AssemblyComponent newComponent = AssemblyFactory.eINSTANCE.createAssemblyComponent();
         newComponent.setSignature(component.getSignature());
 
+        if (component.getComponentType().eIsProxy()) {
+            throw new InternalError(
+                    "Unresolved component type for " + component.getSignature() + " probably broken reference URI");
+        }
+
         // TODO the following fails.
         newComponent.setComponentType(
                 AssemblyModelCloneUtils.findComponentType(typeModel, component.getComponentType().getSignature()));
@@ -77,6 +82,9 @@ public final class AssemblyModelCloneUtils {
     }
 
     private static ComponentType findComponentType(final TypeModel typeModel, final String signature) {
+        if (signature == null) {
+            throw new InternalError("Try to find signature, bit signature is null");
+        }
         return typeModel.getComponentTypes().get(signature);
     }
 }
diff --git a/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/AssemblyModelMerger.java b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/AssemblyModelMerger.java
new file mode 100644
index 0000000000000000000000000000000000000000..4af05e4753d8df41857091d0e1190585183e59b4
--- /dev/null
+++ b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/AssemblyModelMerger.java
@@ -0,0 +1,73 @@
+/***************************************************************************
+ * Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
+package org.oceandsl.tools.mop.merge;
+
+import org.eclipse.emf.common.util.EMap;
+
+import kieker.model.analysismodel.assembly.AssemblyComponent;
+import kieker.model.analysismodel.assembly.AssemblyModel;
+import kieker.model.analysismodel.assembly.AssemblyOperation;
+import kieker.model.analysismodel.assembly.AssemblyStorage;
+import kieker.model.analysismodel.type.TypeModel;
+
+/**
+ * @author Reiner Jung
+ * @since 1.1
+ */
+public final class AssemblyModelMerger {
+
+    private AssemblyModelMerger() {
+    }
+
+    static void mergeAssemblyModel(final TypeModel typeModel, final AssemblyModel model,
+            final AssemblyModel mergeModel) {
+        // add additional component types if necessary
+        for (final AssemblyComponent mergeComponent : mergeModel.getAssemblyComponents().values()) {
+            if (!model.getAssemblyComponents().containsKey(mergeComponent.getSignature())) {
+                model.getAssemblyComponents().put(mergeComponent.getSignature(),
+                        AssemblyModelCloneUtils.duplicate(typeModel, mergeComponent));
+            }
+        }
+        // now merge operations
+        for (final AssemblyComponent component : model.getAssemblyComponents().values()) {
+            final AssemblyComponent mergeComponent = mergeModel.getAssemblyComponents().get(component.getSignature());
+            if (mergeComponent != null) {
+                AssemblyModelMerger.mergeAssemblyOperations(component, mergeComponent.getAssemblyOperations());
+                AssemblyModelMerger.mergeAssemblyStorages(component, mergeComponent.getAssemblyStorages());
+            }
+        }
+    }
+
+    private static void mergeAssemblyOperations(final AssemblyComponent component,
+            final EMap<String, AssemblyOperation> assemblyOperations) {
+        for (final AssemblyOperation mergeOperation : assemblyOperations.values()) {
+            if (!component.getAssemblyOperations().containsKey(mergeOperation.getOperationType().getSignature())) {
+                component.getAssemblyOperations().put(mergeOperation.getOperationType().getSignature(),
+                        AssemblyModelCloneUtils.duplicate(component.getComponentType(), mergeOperation));
+            }
+        }
+    }
+
+    private static void mergeAssemblyStorages(final AssemblyComponent component,
+            final EMap<String, AssemblyStorage> mergeAssemblyStorages) {
+        for (final AssemblyStorage mergeStorage : mergeAssemblyStorages.values()) {
+            if (!component.getAssemblyStorages().containsKey(mergeStorage.getStorageType().getName())) {
+                component.getAssemblyStorages().put(mergeStorage.getStorageType().getName(),
+                        AssemblyModelCloneUtils.duplicate(component.getComponentType(), mergeStorage));
+            }
+        }
+    }
+}
diff --git a/tools/mop/src/main/java/org/oceandsl/tools/mop/operations/DeploymentModelCloneUtils.java b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/DeploymentModelCloneUtils.java
similarity index 99%
rename from tools/mop/src/main/java/org/oceandsl/tools/mop/operations/DeploymentModelCloneUtils.java
rename to tools/mop/src/main/java/org/oceandsl/tools/mop/merge/DeploymentModelCloneUtils.java
index 793d7c04e2cbb9fbff4eeba3ecbe035c2089b0ba..32450dab6f0ac8bc95a635241ecf645b1cccb572 100644
--- a/tools/mop/src/main/java/org/oceandsl/tools/mop/operations/DeploymentModelCloneUtils.java
+++ b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/DeploymentModelCloneUtils.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  ***************************************************************************/
-package org.oceandsl.tools.mop.operations;
+package org.oceandsl.tools.mop.merge;
 
 import java.util.Map.Entry;
 
diff --git a/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/DeploymentModelMerger.java b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/DeploymentModelMerger.java
new file mode 100644
index 0000000000000000000000000000000000000000..55f9074ff33dca71caafadb6d3e9c7d961b96951
--- /dev/null
+++ b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/DeploymentModelMerger.java
@@ -0,0 +1,96 @@
+/***************************************************************************
+ * Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
+package org.oceandsl.tools.mop.merge;
+
+import java.util.Map.Entry;
+
+import org.eclipse.emf.common.util.EMap;
+
+import kieker.model.analysismodel.assembly.AssemblyComponent;
+import kieker.model.analysismodel.assembly.AssemblyModel;
+import kieker.model.analysismodel.deployment.DeployedComponent;
+import kieker.model.analysismodel.deployment.DeployedOperation;
+import kieker.model.analysismodel.deployment.DeployedStorage;
+import kieker.model.analysismodel.deployment.DeploymentContext;
+import kieker.model.analysismodel.deployment.DeploymentModel;
+
+/**
+ * @author Reiner Jung
+ * @since 1.1
+ */
+public class DeploymentModelMerger {
+
+    private DeploymentModelMerger() {
+    }
+
+    static void mergeDeploymentModel(final AssemblyModel assemblyModel, final DeploymentModel model,
+            final DeploymentModel mergeModel) {
+        // add additional contexts if necessary
+        for (final DeploymentContext mergeDeploymentContext : mergeModel.getDeploymentContexts().values()) {
+            if (!model.getDeploymentContexts().containsKey(mergeDeploymentContext.getName())) {
+                model.getDeploymentContexts().put(mergeDeploymentContext.getName(),
+                        DeploymentModelCloneUtils.duplicate(assemblyModel, mergeDeploymentContext));
+            }
+        }
+        // now merge operations
+        for (final DeploymentContext deploymentContext : model.getDeploymentContexts().values()) {
+            final DeploymentContext mergeDeploymentContext = mergeModel.getDeploymentContexts()
+                    .get(deploymentContext.getName());
+            if (mergeDeploymentContext != null) {
+                DeploymentModelMerger.mergeDepolymentComponents(assemblyModel, deploymentContext,
+                        mergeDeploymentContext.getComponents());
+            }
+        }
+
+    }
+
+    private static void mergeDepolymentComponents(final AssemblyModel assemblyModel,
+            final DeploymentContext deploymentContext, final EMap<String, DeployedComponent> components) {
+        for (final DeployedComponent mergeComponent : components.values()) {
+            if (!deploymentContext.getComponents().containsKey(mergeComponent.getSignature())) {
+                deploymentContext.getComponents().put(mergeComponent.getSignature(),
+                        DeploymentModelCloneUtils.duplicate(assemblyModel, mergeComponent));
+            } else {
+                final DeployedComponent component = deploymentContext.getComponents()
+                        .get(mergeComponent.getSignature());
+                DeploymentModelMerger.mergeDeploymentOperations(component.getAssemblyComponent(), component,
+                        mergeComponent.getContainedOperations());
+                DeploymentModelMerger.mergeDeploymentStorages(component.getAssemblyComponent(), component,
+                        mergeComponent.getContainedStorages());
+            }
+        }
+    }
+
+    private static void mergeDeploymentOperations(final AssemblyComponent assemblyComponent,
+            final DeployedComponent component, final EMap<String, DeployedOperation> containedOperations) {
+        for (final Entry<String, DeployedOperation> mergeOperation : containedOperations) {
+            if (!component.getContainedOperations().containsKey(mergeOperation.getKey())) {
+                component.getContainedOperations().put(mergeOperation.getKey(),
+                        DeploymentModelCloneUtils.duplicate(assemblyComponent, mergeOperation.getValue()));
+            }
+        }
+    }
+
+    private static void mergeDeploymentStorages(final AssemblyComponent assemblyComponent,
+            final DeployedComponent component, final EMap<String, DeployedStorage> containedStorages) {
+        for (final Entry<String, DeployedStorage> mergeStorage : containedStorages) {
+            if (!component.getContainedStorages().containsKey(mergeStorage.getKey())) {
+                component.getContainedStorages().put(mergeStorage.getKey(),
+                        DeploymentModelCloneUtils.duplicate(assemblyComponent, mergeStorage.getValue()));
+            }
+        }
+    }
+}
diff --git a/tools/mop/src/main/java/org/oceandsl/tools/mop/operations/ExecutionModelCloneUtils.java b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/ExecutionModelCloneUtils.java
similarity index 92%
rename from tools/mop/src/main/java/org/oceandsl/tools/mop/operations/ExecutionModelCloneUtils.java
rename to tools/mop/src/main/java/org/oceandsl/tools/mop/merge/ExecutionModelCloneUtils.java
index b0abf34c9f0eb3996ee81124f98edc4d869ff177..24ae7d3155a6dfe45908a34e572fd793875095fc 100644
--- a/tools/mop/src/main/java/org/oceandsl/tools/mop/operations/ExecutionModelCloneUtils.java
+++ b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/ExecutionModelCloneUtils.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  ***************************************************************************/
-package org.oceandsl.tools.mop.operations;
+package org.oceandsl.tools.mop.merge;
 
 import kieker.model.analysismodel.deployment.DeployedComponent;
 import kieker.model.analysismodel.deployment.DeployedOperation;
@@ -55,7 +55,7 @@ public final class ExecutionModelCloneUtils {
         return newAccess;
     }
 
-    private static DeployedOperation findDeployedOperation(final DeploymentModel newModel,
+    private static DeployedOperation findDeployedOperation(final DeploymentModel targetModel,
             final DeployedOperation operation) {
         final EStringToDeployedOperationMapEntryImpl mapOperationEntry = (EStringToDeployedOperationMapEntryImpl) operation
                 .eContainer();
@@ -65,13 +65,14 @@ public final class ExecutionModelCloneUtils {
                 .eContainer();
         final DeploymentContext context = (DeploymentContext) mapComponentEntry.eContainer();
 
-        final DeploymentContext newContext = newModel.getDeploymentContexts().get(context.getName());
+        final DeploymentContext newContext = targetModel.getDeploymentContexts().get(context.getName());
         final DeployedComponent newComponent = newContext.getComponents().get(component.getSignature());
+
         return newComponent.getContainedOperations()
                 .get(operation.getAssemblyOperation().getOperationType().getSignature());
     }
 
-    private static DeployedStorage findDeployedStorage(final DeploymentModel newModel, final DeployedStorage storage) {
+    private static DeployedStorage findDeployedStorage(final DeploymentModel targetModel, final DeployedStorage storage) {
         final EStringToDeployedStorageMapEntryImpl mapStorageEntry = (EStringToDeployedStorageMapEntryImpl) storage
                 .eContainer();
         final DeployedComponent component = (DeployedComponent) mapStorageEntry.eContainer();
@@ -80,7 +81,7 @@ public final class ExecutionModelCloneUtils {
                 .eContainer();
         final DeploymentContext context = (DeploymentContext) mapComponentEntry.eContainer();
 
-        final DeploymentContext newContext = newModel.getDeploymentContexts().get(context.getName());
+        final DeploymentContext newContext = targetModel.getDeploymentContexts().get(context.getName());
         final DeployedComponent newComponent = newContext.getComponents().get(component.getSignature());
         return newComponent.getContainedStorages().get(storage.getAssemblyStorage().getStorageType().getName());
     }
diff --git a/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/ExecutionModelMerger.java b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/ExecutionModelMerger.java
new file mode 100644
index 0000000000000000000000000000000000000000..ebb4c257e2308930600bf07aca16dac307459085
--- /dev/null
+++ b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/ExecutionModelMerger.java
@@ -0,0 +1,117 @@
+/***************************************************************************
+ * Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
+package org.oceandsl.tools.mop.merge;
+
+import java.util.Map.Entry;
+
+import org.eclipse.emf.common.util.EMap;
+
+import kieker.model.analysismodel.deployment.DeployedOperation;
+import kieker.model.analysismodel.deployment.DeployedStorage;
+import kieker.model.analysismodel.deployment.DeploymentModel;
+import kieker.model.analysismodel.execution.AggregatedInvocation;
+import kieker.model.analysismodel.execution.AggregatedStorageAccess;
+import kieker.model.analysismodel.execution.EDirection;
+import kieker.model.analysismodel.execution.ExecutionFactory;
+import kieker.model.analysismodel.execution.ExecutionModel;
+import kieker.model.analysismodel.execution.Tuple;
+
+/**
+ * @author Reiner Jung
+ * @since
+ */
+public final class ExecutionModelMerger {
+
+    private ExecutionModelMerger() {
+    }
+
+    static void mergeExecutionModel(final DeploymentModel deploymentModel, final ExecutionModel targetModel,
+            final ExecutionModel mergeModel) {
+        for (final Entry<Tuple<DeployedOperation, DeployedOperation>, AggregatedInvocation> entry : mergeModel
+                .getAggregatedInvocations()) {
+            if (!ExecutionModelMerger.compareTupleOperationKeys(targetModel.getAggregatedInvocations(),
+                    entry.getKey())) {
+                final AggregatedInvocation value = ExecutionModelCloneUtils.duplicate(deploymentModel,
+                        entry.getValue());
+                final Tuple<DeployedOperation, DeployedOperation> key = ExecutionFactory.eINSTANCE.createTuple();
+                key.setFirst(value.getSource());
+                key.setSecond(value.getTarget());
+                targetModel.getAggregatedInvocations().put(key, value);
+            }
+        }
+        for (final Entry<Tuple<DeployedOperation, DeployedStorage>, AggregatedStorageAccess> entry : mergeModel
+                .getAggregatedStorageAccesses()) {
+            final Tuple<DeployedOperation, DeployedStorage> targetModelKey = ExecutionModelMerger
+                    .findTupleStorageKeys(targetModel.getAggregatedStorageAccesses(), entry.getKey());
+            if (targetModelKey == null) {
+                final AggregatedStorageAccess value = ExecutionModelCloneUtils.duplicate(deploymentModel,
+                        entry.getValue());
+                final Tuple<DeployedOperation, DeployedStorage> key = ExecutionFactory.eINSTANCE.createTuple();
+                key.setFirst(value.getCode());
+                key.setSecond(value.getStorage());
+                targetModel.getAggregatedStorageAccesses().put(key, value);
+            } else {
+                final AggregatedStorageAccess targetStorageAccess = targetModel.getAggregatedStorageAccesses()
+                        .get(targetModelKey);
+                final AggregatedStorageAccess sourceStorageAccess = entry.getValue();
+                switch (sourceStorageAccess.getDirection()) {
+                case READ:
+                    if (targetStorageAccess.getDirection() == EDirection.WRITE) {
+                        targetStorageAccess.setDirection(EDirection.BOTH);
+                    }
+                    break;
+                case WRITE:
+                    if (targetStorageAccess.getDirection() == EDirection.READ) {
+                        targetStorageAccess.setDirection(EDirection.BOTH);
+                    }
+                    break;
+                case BOTH:
+                    targetStorageAccess.setDirection(EDirection.BOTH);
+                    break;
+                default:
+                    throw new InternalError(
+                            "Found unsupported direction type " + sourceStorageAccess.getDirection().getName());
+                }
+                targetModel.getAggregatedStorageAccesses().put(targetModelKey, targetStorageAccess);
+            }
+        }
+
+    }
+
+    private static boolean compareTupleOperationKeys(
+            final EMap<Tuple<DeployedOperation, DeployedOperation>, AggregatedInvocation> aggregatedInvocations,
+            final Tuple<DeployedOperation, DeployedOperation> key) {
+        for (final Tuple<DeployedOperation, DeployedOperation> invocationKey : aggregatedInvocations.keySet()) {
+            if (ModelUtils.isEqual(invocationKey.getFirst(), key.getFirst())
+                    && ModelUtils.isEqual(invocationKey.getSecond(), key.getSecond())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static Tuple<DeployedOperation, DeployedStorage> findTupleStorageKeys(
+            final EMap<Tuple<DeployedOperation, DeployedStorage>, AggregatedStorageAccess> aggregatedStorageAccesses,
+            final Tuple<DeployedOperation, DeployedStorage> key) {
+        for (final Tuple<DeployedOperation, DeployedStorage> invocationKey : aggregatedStorageAccesses.keySet()) {
+            if (ModelUtils.isEqual(invocationKey.getFirst(), key.getFirst())
+                    && ModelUtils.isEqual(invocationKey.getSecond(), key.getSecond())) {
+                return invocationKey;
+            }
+        }
+        return null;
+    }
+}
diff --git a/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/ModelRepositoryMerger.java b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/ModelRepositoryMerger.java
new file mode 100644
index 0000000000000000000000000000000000000000..eb44b02f0ee51dde9a9443b40974d3ce9001ea1e
--- /dev/null
+++ b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/ModelRepositoryMerger.java
@@ -0,0 +1,54 @@
+/***************************************************************************
+ * Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
+package org.oceandsl.tools.mop.merge;
+
+import kieker.analysis.stage.model.ModelRepository;
+import kieker.model.analysismodel.assembly.AssemblyModel;
+import kieker.model.analysismodel.deployment.DeploymentModel;
+import kieker.model.analysismodel.execution.ExecutionModel;
+import kieker.model.analysismodel.sources.SourceModel;
+import kieker.model.analysismodel.statistics.StatisticsModel;
+import kieker.model.analysismodel.type.TypeModel;
+
+/**
+ * Merge two different model repositories
+ *
+ * @author Reiner Jung
+ * @since 1.1
+ */
+public class ModelRepositoryMerger {
+
+    public static void perform(final ModelRepository lastModelRepository, final ModelRepository mergeModelRepository) {
+        TypeModelMerger.mergeTypeModel(lastModelRepository.getModel(TypeModel.class),
+                mergeModelRepository.getModel(TypeModel.class));
+        AssemblyModelMerger.mergeAssemblyModel(lastModelRepository.getModel(TypeModel.class),
+                lastModelRepository.getModel(AssemblyModel.class), mergeModelRepository.getModel(AssemblyModel.class));
+        DeploymentModelMerger.mergeDeploymentModel(lastModelRepository.getModel(AssemblyModel.class),
+                lastModelRepository.getModel(DeploymentModel.class),
+                mergeModelRepository.getModel(DeploymentModel.class));
+        ExecutionModelMerger.mergeExecutionModel(lastModelRepository.getModel(DeploymentModel.class),
+                lastModelRepository.getModel(ExecutionModel.class),
+                mergeModelRepository.getModel(ExecutionModel.class));
+        StatisticsModelMerger.mergeStatisticsModel(lastModelRepository.getModel(ExecutionModel.class),
+                lastModelRepository.getModel(StatisticsModel.class),
+                mergeModelRepository.getModel(StatisticsModel.class));
+        SourceModelMerger.mergeSourceModel(lastModelRepository.getModel(TypeModel.class),
+                lastModelRepository.getModel(AssemblyModel.class), lastModelRepository.getModel(DeploymentModel.class),
+                lastModelRepository.getModel(ExecutionModel.class), lastModelRepository.getModel(SourceModel.class),
+                mergeModelRepository.getModel(SourceModel.class));
+    }
+
+}
diff --git a/tools/mop/src/main/java/org/oceandsl/tools/mop/operations/ModelUtils.java b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/ModelUtils.java
similarity index 65%
rename from tools/mop/src/main/java/org/oceandsl/tools/mop/operations/ModelUtils.java
rename to tools/mop/src/main/java/org/oceandsl/tools/mop/merge/ModelUtils.java
index deb8dd1c29db95bfd08c7edacbff17eab9d74717..ad813f5085fa1830b7efdbb3dc5fd72de7d4c68e 100644
--- a/tools/mop/src/main/java/org/oceandsl/tools/mop/operations/ModelUtils.java
+++ b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/ModelUtils.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  ***************************************************************************/
-package org.oceandsl.tools.mop.operations;
+package org.oceandsl.tools.mop.merge;
 
 import java.util.Map.Entry;
 
@@ -32,6 +32,7 @@ import kieker.model.analysismodel.deployment.DeployedStorage;
 import kieker.model.analysismodel.deployment.DeploymentContext;
 import kieker.model.analysismodel.execution.AggregatedInvocation;
 import kieker.model.analysismodel.execution.AggregatedStorageAccess;
+import kieker.model.analysismodel.execution.EDirection;
 import kieker.model.analysismodel.execution.Tuple;
 import kieker.model.analysismodel.type.ComponentType;
 import kieker.model.analysismodel.type.OperationType;
@@ -45,36 +46,36 @@ public class ModelUtils {
 
     public static boolean areObjectsEqual(final EObject left, final EObject right) {
         if (left.getClass().equals(right.getClass())) {
-            if (right instanceof DeployedOperation) {
-                return ModelUtils.isEqual((DeployedOperation) right, (DeployedOperation) left);
-            } else if (right instanceof DeployedStorage) {
-                return ModelUtils.isEqual((DeployedStorage) right, (DeployedStorage) left);
-            } else if (right instanceof DeployedComponent) {
-                return ModelUtils.isEqual((DeployedComponent) right, (DeployedComponent) left);
-            } else if (right instanceof DeploymentContext) {
-                return ModelUtils.isEqual((DeploymentContext) right, (DeploymentContext) left);
-            } else if (right instanceof AssemblyOperation) {
-                return ModelUtils.isEqual((AssemblyOperation) right, (AssemblyOperation) left);
-            } else if (right instanceof AssemblyComponent) {
-                return ModelUtils.isEqual((AssemblyComponent) right, (AssemblyComponent) left);
-            } else if (right instanceof AssemblyOperation) {
-                return ModelUtils.isEqual((AssemblyOperation) right, (AssemblyOperation) left);
-            } else if (right instanceof AssemblyStorage) {
-                return ModelUtils.isEqual((AssemblyStorage) right, (AssemblyStorage) left);
-            } else if (right instanceof ComponentType) {
-                return ModelUtils.isEqual((ComponentType) right, (ComponentType) left);
-            } else if (right instanceof OperationType) {
-                return ModelUtils.isEqual((OperationType) right, (OperationType) left);
-            } else if (right instanceof StorageType) {
-                return ModelUtils.isEqual((StorageType) right, (StorageType) left);
-            } else if (right instanceof AggregatedInvocation) {
-                return ModelUtils.isEqual((AggregatedInvocation) right, (AggregatedInvocation) left);
-            } else if (right instanceof AggregatedStorageAccess) {
-                return ModelUtils.isEqual((AggregatedStorageAccess) right, (AggregatedStorageAccess) left);
-            } else if (right instanceof Tuple) {
-                return ModelUtils.isEqual((Tuple<?, ?>) right, (Tuple<?, ?>) left);
+            if (left instanceof DeployedOperation) {
+                return ModelUtils.isEqual((DeployedOperation) left, (DeployedOperation) right);
+            } else if (left instanceof DeployedStorage) {
+                return ModelUtils.isEqual((DeployedStorage) left, (DeployedStorage) right);
+            } else if (left instanceof DeployedComponent) {
+                return ModelUtils.isEqual((DeployedComponent) left, (DeployedComponent) right);
+            } else if (left instanceof DeploymentContext) {
+                return ModelUtils.isEqual((DeploymentContext) left, (DeploymentContext) right);
+            } else if (left instanceof AssemblyOperation) {
+                return ModelUtils.isEqual((AssemblyOperation) left, (AssemblyOperation) right);
+            } else if (left instanceof AssemblyComponent) {
+                return ModelUtils.isEqual((AssemblyComponent) left, (AssemblyComponent) right);
+            } else if (left instanceof AssemblyOperation) {
+                return ModelUtils.isEqual((AssemblyOperation) left, (AssemblyOperation) right);
+            } else if (left instanceof AssemblyStorage) {
+                return ModelUtils.isEqual((AssemblyStorage) left, (AssemblyStorage) right);
+            } else if (left instanceof ComponentType) {
+                return ModelUtils.isEqual((ComponentType) left, (ComponentType) right);
+            } else if (left instanceof OperationType) {
+                return ModelUtils.isEqual((OperationType) left, (OperationType) right);
+            } else if (left instanceof StorageType) {
+                return ModelUtils.isEqual((StorageType) left, (StorageType) right);
+            } else if (left instanceof AggregatedInvocation) {
+                return ModelUtils.isEqual((AggregatedInvocation) left, (AggregatedInvocation) right);
+            } else if (left instanceof AggregatedStorageAccess) {
+                return ModelUtils.isEqual((AggregatedStorageAccess) left, (AggregatedStorageAccess) right);
+            } else if (left instanceof Tuple) {
+                return ModelUtils.isEqual((Tuple<?, ?>) left, (Tuple<?, ?>) right);
             } else {
-                System.err.println("Missing support for " + right.getClass().getCanonicalName());
+                System.err.println("Missing support for " + left.getClass().getCanonicalName());
             }
         }
         return false;
@@ -86,29 +87,52 @@ public class ModelUtils {
     }
 
     public static boolean isEqual(final AggregatedStorageAccess leftStorageAccess,
-            final AggregatedStorageAccess storageAccess) {
-        return ModelUtils.isEqual(leftStorageAccess.getCode(), storageAccess.getCode())
-                && leftStorageAccess.getDirection().equals(storageAccess.getDirection())
-                && ModelUtils.isEqual(leftStorageAccess.getStorage(), storageAccess.getStorage());
+            final AggregatedStorageAccess rightStorageAccess) {
+        ModelUtils.check(leftStorageAccess, "AggregatedStorageAccess leftStorageAccess");
+        ModelUtils.check(rightStorageAccess, "AggregatedStorageAccess rightStorageAccess");
+        return ModelUtils.isEqual(leftStorageAccess.getCode(), rightStorageAccess.getCode())
+                && ModelUtils.compareDirections(leftStorageAccess.getDirection(), rightStorageAccess.getDirection())
+                && ModelUtils.isEqual(leftStorageAccess.getStorage(), rightStorageAccess.getStorage());
+    }
+
+    private static boolean compareDirections(final EDirection leftDirection, final EDirection rightDirection) {
+        switch (leftDirection) {
+        case READ:
+            return rightDirection == EDirection.READ;
+        case WRITE:
+            return rightDirection == EDirection.WRITE;
+        case BOTH:
+            return true;
+        default:
+            throw new InternalError("Found unsupported Direction " + leftDirection.getName());
+        }
     }
 
     public static boolean isEqual(final DeployedStorage leftStorage, final DeployedStorage storage) {
+        ModelUtils.check(leftStorage, "DeployedStorage leftStorage");
+        ModelUtils.check(storage, "DeployedStorage storage");
         return ModelUtils.isEqual(leftStorage.getAssemblyStorage(), storage.getAssemblyStorage())
                 && ModelUtils.isEqual(leftStorage.getComponent(), storage.getComponent());
     }
 
     public static boolean isEqual(final AssemblyStorage leftAssemblyStorage, final AssemblyStorage assemblyStorage) {
+        ModelUtils.check(leftAssemblyStorage, "AssemblyStorage leftAssemblyStorage");
+        ModelUtils.check(assemblyStorage, "AssemblyStorage assemblyStorage");
         return ModelUtils.isEqual(leftAssemblyStorage.getStorageType(), assemblyStorage.getStorageType()) && ModelUtils
                 .isEqual(leftAssemblyStorage.getAssemblyComponent(), assemblyStorage.getAssemblyComponent());
     }
 
     public static boolean isEqual(final AggregatedInvocation leftInvocation,
             final AggregatedInvocation rightInvocation) {
+        ModelUtils.check(leftInvocation, "AggregatedInvocation leftInvocation");
+        ModelUtils.check(rightInvocation, "AggregatedInvocation rightInvocation");
         return ModelUtils.isEqual(leftInvocation.getSource(), rightInvocation.getSource())
                 && ModelUtils.isEqual(leftInvocation.getTarget(), rightInvocation.getTarget());
     }
 
     public static boolean isEqual(final DeployedOperation leftKey, final DeployedOperation rightKey) {
+        ModelUtils.check(leftKey, "DeployedOperation leftKey");
+        ModelUtils.check(rightKey, "DeployedOperation rightKey");
         return ModelUtils.isEqual(leftKey.getComponent(), rightKey.getComponent())
                 && ModelUtils.isEqual(leftKey.getAssemblyOperation(), rightKey.getAssemblyOperation());
     }
@@ -134,6 +158,8 @@ public class ModelUtils {
 
     public static boolean isEqual(final AssemblyComponent leftAssemblyComponent,
             final AssemblyComponent assemblyComponent) {
+        ModelUtils.check(leftAssemblyComponent, "AssemblyComponent leftAssemblyComponent");
+        ModelUtils.check(assemblyComponent, "AssemblyComponent assemblyComponent");
         return leftAssemblyComponent.getSignature().equals(assemblyComponent.getSignature())
                 && ModelUtils.isEqual(leftAssemblyComponent.getComponentType(), assemblyComponent.getComponentType());
     }
@@ -194,4 +220,12 @@ public class ModelUtils {
         }
     }
 
+    private static void check(final EObject object, final String name) {
+        if (object == null) {
+            throw new InternalError("Object of type " + name + " is null");
+        }
+        if (object.eIsProxy()) {
+            throw new InternalError("Object of type " + name + " could not be resolved.");
+        }
+    }
 }
diff --git a/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/SourceModelMerger.java b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/SourceModelMerger.java
new file mode 100644
index 0000000000000000000000000000000000000000..3a46c0fc5f1a604a40ca0e5e91afd2145d44826a
--- /dev/null
+++ b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/SourceModelMerger.java
@@ -0,0 +1,119 @@
+/***************************************************************************
+ * Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
+package org.oceandsl.tools.mop.merge;
+
+import java.util.Map.Entry;
+
+import org.eclipse.emf.common.util.BasicEList;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.EMap;
+import org.eclipse.emf.common.util.TreeIterator;
+import org.eclipse.emf.ecore.EObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import kieker.model.analysismodel.assembly.AssemblyModel;
+import kieker.model.analysismodel.deployment.DeploymentModel;
+import kieker.model.analysismodel.execution.ExecutionModel;
+import kieker.model.analysismodel.sources.SourceModel;
+import kieker.model.analysismodel.type.TypeModel;
+
+/**
+ * @author Reiner Jung
+ * @since
+ */
+public final class SourceModelMerger {
+
+    private final static Logger LOGGER = LoggerFactory.getLogger(SourceModelMerger.class);
+
+    private SourceModelMerger() {
+    }
+
+    static void mergeSourceModel(final TypeModel typeModel, final AssemblyModel assemblyModel,
+            final DeploymentModel deploymentModel, final ExecutionModel executionModel, final SourceModel model,
+            final SourceModel mergeModel) {
+        for (final Entry<EObject, EList<String>> mergeSource : mergeModel.getSources()) {
+            final EObject modelKey = SourceModelMerger.findCorrespondingKey(model.getSources(), mergeSource.getKey());
+            if (modelKey != null) {
+                final EList<String> modelSource = model.getSources().get(modelKey);
+                if (modelSource == null) {
+                    SourceModelMerger.LOGGER.error("Model error no sources for existing key {}", modelKey);
+                    model.getSources().put(modelKey, mergeSource.getValue());
+                } else {
+                    SourceModelMerger.mergeSources(modelSource, mergeSource.getValue());
+                }
+            } else {
+                final EList<String> modelSources = new BasicEList<>();
+                SourceModelMerger.mergeSources(modelSources, mergeSource.getValue());
+                model.getSources().put(SourceModelMerger.findCorrespondingObject(typeModel, assemblyModel,
+                        deploymentModel, executionModel, mergeSource.getKey()), modelSources);
+            }
+        }
+    }
+
+    private static EObject findCorrespondingObject(final TypeModel typeModel, final AssemblyModel assemblyModel,
+            final DeploymentModel deploymentModel, final ExecutionModel executionModel, final EObject key) {
+        EObject result = SourceModelMerger.findObjectInModel(typeModel.eAllContents(), key);
+        if (result != null) {
+            return result;
+        }
+
+        result = SourceModelMerger.findObjectInModel(assemblyModel.eAllContents(), key);
+        if (result != null) {
+            return result;
+        }
+
+        result = SourceModelMerger.findObjectInModel(deploymentModel.eAllContents(), key);
+        if (result != null) {
+            return result;
+        }
+
+        result = SourceModelMerger.findObjectInModel(executionModel.eAllContents(), key);
+        if (result != null) {
+            return result;
+        }
+
+        return null;
+    }
+
+    private static EObject findObjectInModel(final TreeIterator<EObject> iterator, final EObject key) {
+        while (iterator.hasNext()) {
+            final EObject item = iterator.next();
+            if (ModelUtils.areObjectsEqual(key, item)) {
+                return item;
+            }
+        }
+
+        return null;
+    }
+
+    private static void mergeSources(final EList<String> modelSource, final EList<String> mergeSource) {
+        for (final String value : mergeSource) {
+            if (!modelSource.contains(value)) {
+                modelSource.add(value);
+            }
+        }
+    }
+
+    private static EObject findCorrespondingKey(final EMap<EObject, EList<String>> sources, final EObject mergeKey) {
+        for (final EObject key : sources.keySet()) {
+            if (ModelUtils.areObjectsEqual(key, mergeKey)) {
+                return key;
+            }
+        }
+        return null;
+    }
+}
diff --git a/tools/mop/src/main/java/org/oceandsl/tools/mop/operations/StatisticsModelCloneUtils.java b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/StatisticsModelCloneUtils.java
similarity index 98%
rename from tools/mop/src/main/java/org/oceandsl/tools/mop/operations/StatisticsModelCloneUtils.java
rename to tools/mop/src/main/java/org/oceandsl/tools/mop/merge/StatisticsModelCloneUtils.java
index 77b27680e3dd9e236a259b1300f7a38aeadad048..f18876f06aca7f8bf370302ff65396849e083830 100644
--- a/tools/mop/src/main/java/org/oceandsl/tools/mop/operations/StatisticsModelCloneUtils.java
+++ b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/StatisticsModelCloneUtils.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  ***************************************************************************/
-package org.oceandsl.tools.mop.operations;
+package org.oceandsl.tools.mop.merge;
 
 import java.util.Map.Entry;
 
diff --git a/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/StatisticsModelMerger.java b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/StatisticsModelMerger.java
new file mode 100644
index 0000000000000000000000000000000000000000..3d52fdb9f439f7cb37e0fc1553603c54bceef218
--- /dev/null
+++ b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/StatisticsModelMerger.java
@@ -0,0 +1,119 @@
+/***************************************************************************
+ * Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
+package org.oceandsl.tools.mop.merge;
+
+import java.util.Map.Entry;
+
+import org.apache.commons.lang3.NotImplementedException;
+import org.eclipse.emf.common.util.EMap;
+import org.eclipse.emf.ecore.EObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import kieker.model.analysismodel.execution.AggregatedInvocation;
+import kieker.model.analysismodel.execution.AggregatedStorageAccess;
+import kieker.model.analysismodel.execution.ExecutionModel;
+import kieker.model.analysismodel.statistics.EPredefinedUnits;
+import kieker.model.analysismodel.statistics.EPropertyType;
+import kieker.model.analysismodel.statistics.StatisticRecord;
+import kieker.model.analysismodel.statistics.Statistics;
+import kieker.model.analysismodel.statistics.StatisticsModel;
+
+/**
+ * @author Reiner Jung
+ * @since
+ */
+public final class StatisticsModelMerger {
+
+    private final static Logger LOGGER = LoggerFactory.getLogger(StatisticsModelMerger.class);
+
+    private StatisticsModelMerger() {
+    }
+
+    static void mergeStatisticsModel(final ExecutionModel executionModel, final StatisticsModel targetModel,
+            final StatisticsModel mergeModel) {
+        for (final Entry<EObject, Statistics> mergeStatistic : mergeModel.getStatistics()) {
+            /*
+             * Unfortunately the map function containsKey does not match the correct keys, as the
+             * hash value is computed also over references which belong to another model. Thus, the
+             * containsKey always fails.
+             */
+            final EObject targetStatisticKey = StatisticsModelMerger.findKey(targetModel.getStatistics(),
+                    mergeStatistic.getKey());
+            if (targetStatisticKey == null) {
+                targetModel.getStatistics().put(
+                        StatisticsModelMerger.createExecutionModelKey(executionModel, mergeStatistic.getKey()),
+                        StatisticsModelCloneUtils.duplicate(mergeStatistic.getValue()));
+            } else {
+                final Statistics newStatistic = targetModel.getStatistics().get(targetStatisticKey);
+                for (final Entry<EPredefinedUnits, StatisticRecord> statisticRecord : mergeStatistic.getValue()
+                        .getStatistics()) {
+                    if (!newStatistic.getStatistics().containsKey(statisticRecord.getKey())) {
+                        newStatistic.getStatistics().put(statisticRecord.getKey(),
+                                StatisticsModelCloneUtils.duplicate(statisticRecord.getValue()));
+                    } else {
+                        final StatisticRecord newRecord = newStatistic.getStatistics().get(statisticRecord.getKey());
+                        for (final Entry<EPropertyType, Object> property : statisticRecord.getValue().getProperties()) {
+                            if (!newRecord.getProperties().containsKey(property.getKey())) {
+                                newRecord.getProperties().put(property.getKey(),
+                                        StatisticsModelCloneUtils.duplicateObject(property.getValue()));
+                            } else {
+                                final Object newValue = StatisticsModelCloneUtils
+                                        .compute(newRecord.getProperties().get(property.getKey()), property.getValue());
+                                newRecord.getProperties().put(property.getKey(), newValue);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private static EObject createExecutionModelKey(final ExecutionModel executionModel, final EObject key) {
+        if (key instanceof AggregatedInvocation) {
+            for (final AggregatedInvocation invocation : executionModel.getAggregatedInvocations().values()) {
+                if (ModelUtils.areObjectsEqual(key, invocation)) {
+                    return invocation;
+                }
+            }
+            StatisticsModelMerger.LOGGER.error("Missing correpsonding {} in the merged model.", key.getClass());
+            throw new InternalError(String.format("Missing correpsonding %s in the merged model.", key.getClass()));
+        } else if (key instanceof AggregatedStorageAccess) {
+            for (final AggregatedStorageAccess storageAccess : executionModel.getAggregatedStorageAccesses().values()) {
+                final AggregatedStorageAccess searchForStorageAccess = (AggregatedStorageAccess) key;
+                if (ModelUtils.areObjectsEqual(searchForStorageAccess, storageAccess)) {
+                    return storageAccess;
+                }
+            }
+            StatisticsModelMerger.LOGGER.error("Missing correpsonding {} in the merged model.", key.getClass());
+            throw new InternalError(String.format("Missing correpsonding %s in the merged model.", key.getClass()));
+        } else {
+            StatisticsModelMerger.LOGGER.error("Statistics related to {} objects are not yet supported.",
+                    key.getClass());
+            throw new NotImplementedException(
+                    String.format("Statistics related to %s objects are not yet supported.", key.getClass()));
+        }
+    }
+
+    private static EObject findKey(final EMap<EObject, Statistics> statistics, final EObject key) {
+        for (final EObject mapkey : statistics.keySet()) {
+            if (ModelUtils.areObjectsEqual(mapkey, key)) {
+                return mapkey;
+            }
+        }
+        return null;
+    }
+}
diff --git a/tools/mop/src/main/java/org/oceandsl/tools/mop/operations/TypeModelCloneUtils.java b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/TypeModelCloneUtils.java
similarity index 98%
rename from tools/mop/src/main/java/org/oceandsl/tools/mop/operations/TypeModelCloneUtils.java
rename to tools/mop/src/main/java/org/oceandsl/tools/mop/merge/TypeModelCloneUtils.java
index 800d2f936476bfba743fd3aab3f7a5561664448f..e10a2480fb2259e71b3e2b9c904b3758395a3854 100644
--- a/tools/mop/src/main/java/org/oceandsl/tools/mop/operations/TypeModelCloneUtils.java
+++ b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/TypeModelCloneUtils.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  ***************************************************************************/
-package org.oceandsl.tools.mop.operations;
+package org.oceandsl.tools.mop.merge;
 
 import java.util.Map.Entry;
 
diff --git a/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/TypeModelMerger.java b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/TypeModelMerger.java
new file mode 100644
index 0000000000000000000000000000000000000000..e6e576861cee74867b58d0a335a39069d48f896a
--- /dev/null
+++ b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/TypeModelMerger.java
@@ -0,0 +1,69 @@
+/***************************************************************************
+ * Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
+package org.oceandsl.tools.mop.merge;
+
+import org.eclipse.emf.common.util.EMap;
+
+import kieker.model.analysismodel.type.ComponentType;
+import kieker.model.analysismodel.type.OperationType;
+import kieker.model.analysismodel.type.StorageType;
+import kieker.model.analysismodel.type.TypeModel;
+
+/**
+ * @author Reiner Jung
+ * @since 1.1
+ */
+public final class TypeModelMerger {
+
+    private TypeModelMerger() {
+    }
+
+    static void mergeTypeModel(final TypeModel model, final TypeModel mergeModel) {
+        // add additional component types if necessary
+        for (final ComponentType mergeType : mergeModel.getComponentTypes().values()) {
+            if (!model.getComponentTypes().containsKey(mergeType.getSignature())) {
+                model.getComponentTypes().put(mergeType.getSignature(), TypeModelCloneUtils.duplicate(mergeType));
+            }
+        }
+        // now merge operations
+        for (final ComponentType type : model.getComponentTypes().values()) {
+            final ComponentType mergeType = mergeModel.getComponentTypes().get(type.getSignature());
+            if (mergeType != null) {
+                TypeModelMerger.mergeTypeOperations(type, mergeType.getProvidedOperations());
+                TypeModelMerger.mergeTypeStorages(type, mergeType.getProvidedStorages());
+            }
+        }
+    }
+
+    private static void mergeTypeOperations(final ComponentType type,
+            final EMap<String, OperationType> mergeProvidedOperations) {
+        for (final OperationType mergeOperation : mergeProvidedOperations.values()) {
+            if (!type.getProvidedOperations().containsKey(mergeOperation.getSignature())) {
+                type.getProvidedOperations().put(mergeOperation.getSignature(),
+                        TypeModelCloneUtils.duplicate(mergeOperation));
+            }
+        }
+    }
+
+    private static void mergeTypeStorages(final ComponentType type, final EMap<String, StorageType> providedStorages) {
+        for (final StorageType mergeStorage : providedStorages.values()) {
+            if (!type.getProvidedStorages().containsKey(mergeStorage.getName())) {
+                type.getProvidedStorages().put(mergeStorage.getName(), TypeModelCloneUtils.duplicate(mergeStorage));
+            }
+        }
+    }
+
+}
diff --git a/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/package-info.java b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/package-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..9cfb9113d8562d0c97ec952fb336752b66560d71
--- /dev/null
+++ b/tools/mop/src/main/java/org/oceandsl/tools/mop/merge/package-info.java
@@ -0,0 +1 @@
+package org.oceandsl.tools.mop.merge;
\ No newline at end of file
diff --git a/tools/mop/src/main/java/org/oceandsl/tools/mop/operations/ModelRepositoryMerger.java b/tools/mop/src/main/java/org/oceandsl/tools/mop/operations/ModelRepositoryMerger.java
deleted file mode 100644
index 714f82e19ad59b1d319ca885f86de34048cf6354..0000000000000000000000000000000000000000
--- a/tools/mop/src/main/java/org/oceandsl/tools/mop/operations/ModelRepositoryMerger.java
+++ /dev/null
@@ -1,424 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- ***************************************************************************/
-package org.oceandsl.tools.mop.operations;
-
-import java.util.Map.Entry;
-
-import org.apache.commons.lang3.NotImplementedException;
-import org.eclipse.emf.common.util.BasicEList;
-import org.eclipse.emf.common.util.EList;
-import org.eclipse.emf.common.util.EMap;
-import org.eclipse.emf.common.util.TreeIterator;
-import org.eclipse.emf.ecore.EObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import kieker.analysis.stage.model.ModelRepository;
-import kieker.model.analysismodel.assembly.AssemblyComponent;
-import kieker.model.analysismodel.assembly.AssemblyModel;
-import kieker.model.analysismodel.assembly.AssemblyOperation;
-import kieker.model.analysismodel.assembly.AssemblyStorage;
-import kieker.model.analysismodel.deployment.DeployedComponent;
-import kieker.model.analysismodel.deployment.DeployedOperation;
-import kieker.model.analysismodel.deployment.DeployedStorage;
-import kieker.model.analysismodel.deployment.DeploymentContext;
-import kieker.model.analysismodel.deployment.DeploymentModel;
-import kieker.model.analysismodel.execution.AggregatedInvocation;
-import kieker.model.analysismodel.execution.AggregatedStorageAccess;
-import kieker.model.analysismodel.execution.ExecutionFactory;
-import kieker.model.analysismodel.execution.ExecutionModel;
-import kieker.model.analysismodel.execution.Tuple;
-import kieker.model.analysismodel.sources.SourceModel;
-import kieker.model.analysismodel.statistics.EPredefinedUnits;
-import kieker.model.analysismodel.statistics.EPropertyType;
-import kieker.model.analysismodel.statistics.StatisticRecord;
-import kieker.model.analysismodel.statistics.Statistics;
-import kieker.model.analysismodel.statistics.StatisticsModel;
-import kieker.model.analysismodel.type.ComponentType;
-import kieker.model.analysismodel.type.OperationType;
-import kieker.model.analysismodel.type.StorageType;
-import kieker.model.analysismodel.type.TypeModel;
-
-/**
- * Merge two different model repositories
- *
- * @author Reiner Jung
- * @since 1.1
- */
-public class ModelRepositoryMerger {
-
-    final static Logger LOGGER = LoggerFactory.getLogger(ModelRepositoryMerger.class);
-
-    public static void perform(final ModelRepository lastModelRepository, final ModelRepository mergeModelRepository) {
-        ModelRepositoryMerger.mergeTypeModel(lastModelRepository.getModel(TypeModel.class),
-                mergeModelRepository.getModel(TypeModel.class));
-        ModelRepositoryMerger.mergeAssemblyModel(lastModelRepository.getModel(TypeModel.class),
-                lastModelRepository.getModel(AssemblyModel.class), mergeModelRepository.getModel(AssemblyModel.class));
-        ModelRepositoryMerger.mergeDeploymentModel(lastModelRepository.getModel(AssemblyModel.class),
-                lastModelRepository.getModel(DeploymentModel.class),
-                mergeModelRepository.getModel(DeploymentModel.class));
-        ModelRepositoryMerger.mergeExecutionModel(lastModelRepository.getModel(DeploymentModel.class),
-                lastModelRepository.getModel(ExecutionModel.class),
-                mergeModelRepository.getModel(ExecutionModel.class));
-        ModelRepositoryMerger.mergeStatisticsModel(lastModelRepository.getModel(ExecutionModel.class),
-                lastModelRepository.getModel(StatisticsModel.class),
-                mergeModelRepository.getModel(StatisticsModel.class));
-        ModelRepositoryMerger.mergeSourceModel(lastModelRepository.getModel(TypeModel.class),
-                lastModelRepository.getModel(AssemblyModel.class), lastModelRepository.getModel(DeploymentModel.class),
-                lastModelRepository.getModel(ExecutionModel.class), lastModelRepository.getModel(SourceModel.class),
-                mergeModelRepository.getModel(SourceModel.class));
-    }
-
-    private static void mergeTypeModel(final TypeModel model, final TypeModel mergeModel) {
-        // add additional component types if necessary
-        for (final ComponentType mergeType : mergeModel.getComponentTypes().values()) {
-            if (!model.getComponentTypes().containsKey(mergeType.getSignature())) {
-                model.getComponentTypes().put(mergeType.getSignature(), TypeModelCloneUtils.duplicate(mergeType));
-            }
-        }
-        // now merge operations
-        for (final ComponentType type : model.getComponentTypes().values()) {
-            final ComponentType mergeType = mergeModel.getComponentTypes().get(type.getSignature());
-            if (mergeType != null) {
-                ModelRepositoryMerger.mergeTypeOperations(type, mergeType.getProvidedOperations());
-                ModelRepositoryMerger.mergeTypeStorages(type, mergeType.getProvidedStorages());
-            }
-        }
-    }
-
-    private static void mergeTypeOperations(final ComponentType type,
-            final EMap<String, OperationType> mergeProvidedOperations) {
-        for (final OperationType mergeOperation : mergeProvidedOperations.values()) {
-            if (!type.getProvidedOperations().containsKey(mergeOperation.getSignature())) {
-                type.getProvidedOperations().put(mergeOperation.getSignature(),
-                        TypeModelCloneUtils.duplicate(mergeOperation));
-            }
-        }
-    }
-
-    private static void mergeTypeStorages(final ComponentType type, final EMap<String, StorageType> providedStorages) {
-        for (final StorageType mergeStorage : providedStorages.values()) {
-            if (!type.getProvidedStorages().containsKey(mergeStorage.getName())) {
-                type.getProvidedStorages().put(mergeStorage.getName(), TypeModelCloneUtils.duplicate(mergeStorage));
-            }
-        }
-    }
-
-    /** -- assembly model -- */
-
-    private static void mergeAssemblyModel(final TypeModel typeModel, final AssemblyModel model,
-            final AssemblyModel mergeModel) {
-        // add additional component types if necessary
-        for (final AssemblyComponent mergeComponent : mergeModel.getAssemblyComponents().values()) {
-            if (!model.getAssemblyComponents().containsKey(mergeComponent.getSignature())) {
-                model.getAssemblyComponents().put(mergeComponent.getSignature(),
-                        AssemblyModelCloneUtils.duplicate(typeModel, mergeComponent));
-            }
-        }
-        // now merge operations
-        for (final AssemblyComponent component : model.getAssemblyComponents().values()) {
-            final AssemblyComponent mergeComponent = mergeModel.getAssemblyComponents().get(component.getSignature());
-            if (mergeComponent != null) {
-                ModelRepositoryMerger.mergeAssemblyOperations(component, mergeComponent.getAssemblyOperations());
-                ModelRepositoryMerger.mergeAssemblyStorages(component, mergeComponent.getAssemblyStorages());
-            }
-        }
-    }
-
-    private static void mergeAssemblyOperations(final AssemblyComponent component,
-            final EMap<String, AssemblyOperation> assemblyOperations) {
-        for (final AssemblyOperation mergeOperation : assemblyOperations.values()) {
-            if (!component.getAssemblyOperations().containsKey(mergeOperation.getOperationType().getSignature())) {
-                component.getAssemblyOperations().put(mergeOperation.getOperationType().getSignature(),
-                        AssemblyModelCloneUtils.duplicate(component.getComponentType(), mergeOperation));
-            }
-        }
-    }
-
-    private static void mergeAssemblyStorages(final AssemblyComponent component,
-            final EMap<String, AssemblyStorage> assemblyStorages) {
-        for (final AssemblyStorage mergeStorage : assemblyStorages.values()) {
-            if (!component.getAssemblyOperations().containsKey(mergeStorage.getStorageType().getName())) {
-                component.getAssemblyStorages().put(mergeStorage.getStorageType().getName(),
-                        AssemblyModelCloneUtils.duplicate(component.getComponentType(), mergeStorage));
-            }
-        }
-    }
-
-    /** -- deployment -- */
-
-    private static void mergeDeploymentModel(final AssemblyModel assemblyModel, final DeploymentModel model,
-            final DeploymentModel mergeModel) {
-        // add additional contexts if necessary
-        for (final DeploymentContext mergeDeploymentContext : mergeModel.getDeploymentContexts().values()) {
-            if (!model.getDeploymentContexts().containsKey(mergeDeploymentContext.getName())) {
-                model.getDeploymentContexts().put(mergeDeploymentContext.getName(),
-                        DeploymentModelCloneUtils.duplicate(assemblyModel, mergeDeploymentContext));
-            }
-        }
-        // now merge operations
-        for (final DeploymentContext deploymentContext : model.getDeploymentContexts().values()) {
-            final DeploymentContext mergeDeploymentContext = mergeModel.getDeploymentContexts()
-                    .get(deploymentContext.getName());
-            if (mergeDeploymentContext != null) {
-                ModelRepositoryMerger.mergeDepolymentComponents(assemblyModel, deploymentContext,
-                        mergeDeploymentContext.getComponents());
-            }
-        }
-
-    }
-
-    private static void mergeDepolymentComponents(final AssemblyModel assemblyModel,
-            final DeploymentContext deploymentContext, final EMap<String, DeployedComponent> components) {
-        for (final DeployedComponent mergeComponent : components.values()) {
-            if (!deploymentContext.getComponents().containsKey(mergeComponent.getSignature())) {
-                deploymentContext.getComponents().put(mergeComponent.getSignature(),
-                        DeploymentModelCloneUtils.duplicate(assemblyModel, mergeComponent));
-            } else {
-                final DeployedComponent component = deploymentContext.getComponents()
-                        .get(mergeComponent.getSignature());
-                ModelRepositoryMerger.mergeDeploymentOperations(component.getAssemblyComponent(), component,
-                        mergeComponent.getContainedOperations());
-                ModelRepositoryMerger.mergeDeploymentStorages(component.getAssemblyComponent(), component,
-                        mergeComponent.getContainedStorages());
-            }
-        }
-    }
-
-    private static void mergeDeploymentOperations(final AssemblyComponent assemblyComponent,
-            final DeployedComponent component, final EMap<String, DeployedOperation> containedOperations) {
-        for (final Entry<String, DeployedOperation> mergeOperation : containedOperations) {
-            if (!component.getContainedOperations().containsKey(mergeOperation.getKey())) {
-                component.getContainedOperations().put(mergeOperation.getKey(),
-                        DeploymentModelCloneUtils.duplicate(assemblyComponent, mergeOperation.getValue()));
-            }
-        }
-    }
-
-    private static void mergeDeploymentStorages(final AssemblyComponent assemblyComponent,
-            final DeployedComponent component, final EMap<String, DeployedStorage> containedStorages) {
-        for (final Entry<String, DeployedStorage> mergeStorage : containedStorages) {
-            if (!component.getContainedStorages().containsKey(mergeStorage.getKey())) {
-                component.getContainedStorages().put(mergeStorage.getKey(),
-                        DeploymentModelCloneUtils.duplicate(assemblyComponent, mergeStorage.getValue()));
-            }
-        }
-    }
-
-    /** -- execution model -- */
-
-    private static void mergeExecutionModel(final DeploymentModel deploymentModel, final ExecutionModel model,
-            final ExecutionModel mergeModel) {
-        for (final Entry<Tuple<DeployedOperation, DeployedOperation>, AggregatedInvocation> entry : mergeModel
-                .getAggregatedInvocations()) {
-            if (!ModelRepositoryMerger.compareTupleOperationKeys(model.getAggregatedInvocations(), entry.getKey())) {
-                final AggregatedInvocation value = ExecutionModelCloneUtils.duplicate(deploymentModel,
-                        entry.getValue());
-                final Tuple<DeployedOperation, DeployedOperation> key = ExecutionFactory.eINSTANCE.createTuple();
-                key.setFirst(value.getSource());
-                key.setSecond(value.getTarget());
-                model.getAggregatedInvocations().put(key, value);
-            }
-        }
-        for (final Entry<Tuple<DeployedOperation, DeployedStorage>, AggregatedStorageAccess> entry : mergeModel
-                .getAggregatedStorageAccesses()) {
-            if (!ModelRepositoryMerger.compareTupleStorageKeys(model.getAggregatedStorageAccesses(), entry.getKey())) {
-                final AggregatedStorageAccess value = ExecutionModelCloneUtils.duplicate(deploymentModel,
-                        entry.getValue());
-                final Tuple<DeployedOperation, DeployedStorage> key = ExecutionFactory.eINSTANCE.createTuple();
-                key.setFirst(value.getCode());
-                key.setSecond(value.getStorage());
-                model.getAggregatedStorageAccesses().put(key, value);
-            }
-        }
-    }
-
-    private static boolean compareTupleOperationKeys(
-            final EMap<Tuple<DeployedOperation, DeployedOperation>, AggregatedInvocation> aggregatedInvocations,
-            final Tuple<DeployedOperation, DeployedOperation> key) {
-        for (final Tuple<DeployedOperation, DeployedOperation> invocationKey : aggregatedInvocations.keySet()) {
-            if (ModelUtils.isEqual(invocationKey.getFirst(), key.getFirst())
-                    && ModelUtils.isEqual(invocationKey.getSecond(), key.getSecond())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private static boolean compareTupleStorageKeys(
-            final EMap<Tuple<DeployedOperation, DeployedStorage>, AggregatedStorageAccess> aggregatedStorageAccesses,
-            final Tuple<DeployedOperation, DeployedStorage> key) {
-        for (final Tuple<DeployedOperation, DeployedStorage> invocationKey : aggregatedStorageAccesses.keySet()) {
-            if (ModelUtils.isEqual(invocationKey.getFirst(), key.getFirst())
-                    && ModelUtils.isEqual(invocationKey.getSecond(), key.getSecond())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /** -- statistics model -- */
-    private static void mergeStatisticsModel(final ExecutionModel executionModel, final StatisticsModel model,
-            final StatisticsModel mergeModel) {
-        for (final Entry<EObject, Statistics> statistic : mergeModel.getStatistics()) {
-            /*
-             * Unfortunately th map function containsKey does not match the correct keys, as the
-             * hash value is computed also over references which belong to another model. Thus, the
-             * containsKey always fails.
-             */
-            final EObject mergeKey = ModelRepositoryMerger.findKey(model.getStatistics(), statistic.getKey());
-            if (mergeKey == null) {
-                model.getStatistics().put(
-                        ModelRepositoryMerger.createExecutionModelKey(executionModel, statistic.getKey()),
-                        StatisticsModelCloneUtils.duplicate(statistic.getValue()));
-            } else {
-                final Statistics newStatistic = model.getStatistics().get(mergeKey);
-                for (final Entry<EPredefinedUnits, StatisticRecord> statisticRecord : statistic.getValue()
-                        .getStatistics()) {
-                    if (!newStatistic.getStatistics().containsKey(statisticRecord.getKey())) {
-                        newStatistic.getStatistics().put(statisticRecord.getKey(),
-                                StatisticsModelCloneUtils.duplicate(statisticRecord.getValue()));
-                    } else {
-                        final StatisticRecord newRecord = newStatistic.getStatistics().get(statisticRecord.getKey());
-                        for (final Entry<EPropertyType, Object> property : statisticRecord.getValue().getProperties()) {
-                            if (!newRecord.getProperties().containsKey(property.getKey())) {
-                                newRecord.getProperties().put(property.getKey(),
-                                        StatisticsModelCloneUtils.duplicateObject(property.getValue()));
-                            } else {
-                                final Object newValue = StatisticsModelCloneUtils
-                                        .compute(newRecord.getProperties().get(property.getKey()), property.getValue());
-                                newRecord.getProperties().put(property.getKey(), newValue);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    private static EObject createExecutionModelKey(final ExecutionModel executionModel, final EObject key) {
-        if (key instanceof AggregatedInvocation) {
-            for (final AggregatedInvocation invocation : executionModel.getAggregatedInvocations().values()) {
-                if (ModelUtils.areObjectsEqual(key, invocation)) {
-                    return invocation;
-                }
-            }
-            ModelRepositoryMerger.LOGGER.error("Missing correpsonding {} in the merged model.", key.getClass());
-            throw new InternalError(String.format("Missing correpsonding %s in the merged model.", key.getClass()));
-        } else if (key instanceof AggregatedStorageAccess) {
-            for (final AggregatedStorageAccess storageAccess : executionModel.getAggregatedStorageAccesses().values()) {
-                if (ModelUtils.areObjectsEqual(key, storageAccess)) {
-                    return storageAccess;
-                }
-            }
-            ModelRepositoryMerger.LOGGER.error("Missing correpsonding {} in the merged model.", key.getClass());
-            throw new InternalError(String.format("Missing correpsonding %s in the merged model.", key.getClass()));
-        } else {
-            ModelRepositoryMerger.LOGGER.error("Statistics related to {} objects are not yet supported.",
-                    key.getClass());
-            throw new NotImplementedException(
-                    String.format("Statistics related to %s objects are not yet supported.", key.getClass()));
-        }
-    }
-
-    private static EObject findKey(final EMap<EObject, Statistics> statistics, final EObject key) {
-        for (final EObject mapkey : statistics.keySet()) {
-            if (ModelUtils.areObjectsEqual(mapkey, key)) {
-                return mapkey;
-            }
-        }
-        return null;
-    }
-
-    /** -- source model -- */
-
-    private static void mergeSourceModel(final TypeModel typeModel, final AssemblyModel assemblyModel,
-            final DeploymentModel deploymentModel, final ExecutionModel executionModel, final SourceModel model,
-            final SourceModel mergeModel) {
-        for (final Entry<EObject, EList<String>> mergeSource : mergeModel.getSources()) {
-            final EObject modelKey = ModelRepositoryMerger.findCorrespondingKey(model.getSources(),
-                    mergeSource.getKey());
-            if (modelKey != null) {
-                final EList<String> modelSource = model.getSources().get(modelKey);
-                if (modelSource == null) {
-                    ModelRepositoryMerger.LOGGER.error("Model error no sources for existing key {}", modelKey);
-                    model.getSources().put(modelKey, mergeSource.getValue());
-                } else {
-                    ModelRepositoryMerger.mergeSources(modelSource, mergeSource.getValue());
-                }
-            } else {
-                final EList<String> modelSources = new BasicEList<>();
-                ModelRepositoryMerger.mergeSources(modelSources, mergeSource.getValue());
-                model.getSources().put(ModelRepositoryMerger.findCorrespondingObject(typeModel, assemblyModel,
-                        deploymentModel, executionModel, mergeSource.getKey()), modelSources);
-            }
-        }
-    }
-
-    private static EObject findCorrespondingObject(final TypeModel typeModel, final AssemblyModel assemblyModel,
-            final DeploymentModel deploymentModel, final ExecutionModel executionModel, final EObject key) {
-        EObject result = ModelRepositoryMerger.findObjectInModel(typeModel.eAllContents(), key);
-        if (result != null) {
-            return result;
-        }
-
-        result = ModelRepositoryMerger.findObjectInModel(assemblyModel.eAllContents(), key);
-        if (result != null) {
-            return result;
-        }
-
-        result = ModelRepositoryMerger.findObjectInModel(deploymentModel.eAllContents(), key);
-        if (result != null) {
-            return result;
-        }
-
-        result = ModelRepositoryMerger.findObjectInModel(executionModel.eAllContents(), key);
-        if (result != null) {
-            return result;
-        }
-
-        return null;
-    }
-
-    private static EObject findObjectInModel(final TreeIterator<EObject> iterator, final EObject key) {
-        while (iterator.hasNext()) {
-            final EObject item = iterator.next();
-            if (ModelUtils.areObjectsEqual(key, item)) {
-                return item;
-            }
-        }
-
-        return null;
-    }
-
-    private static void mergeSources(final EList<String> modelSource, final EList<String> mergeSource) {
-        for (final String value : mergeSource) {
-            if (!modelSource.contains(value)) {
-                modelSource.add(value);
-            }
-        }
-    }
-
-    private static EObject findCorrespondingKey(final EMap<EObject, EList<String>> sources, final EObject mergeKey) {
-        for (final EObject key : sources.keySet()) {
-            if (ModelUtils.areObjectsEqual(key, mergeKey)) {
-                return key;
-            }
-        }
-        return null;
-    }
-
-}
diff --git a/tools/mop/src/main/java/org/oceandsl/tools/mop/operations/package-info.java b/tools/mop/src/main/java/org/oceandsl/tools/mop/operations/package-info.java
deleted file mode 100644
index 9d9eb1ab3f62028db019fea878fd3e6c520060dd..0000000000000000000000000000000000000000
--- a/tools/mop/src/main/java/org/oceandsl/tools/mop/operations/package-info.java
+++ /dev/null
@@ -1 +0,0 @@
-package org.oceandsl.tools.mop.operations;
\ No newline at end of file
diff --git a/tools/mop/src/main/java/org/oceandsl/tools/mop/stages/ModelProcessor.java b/tools/mop/src/main/java/org/oceandsl/tools/mop/stages/ModelProcessor.java
index 790ed13d2cab65d0e3d65bc2a0e1d2044c58537b..4be74e1239f6adf271e0ffff03d67638c81e8645 100644
--- a/tools/mop/src/main/java/org/oceandsl/tools/mop/stages/ModelProcessor.java
+++ b/tools/mop/src/main/java/org/oceandsl/tools/mop/stages/ModelProcessor.java
@@ -16,7 +16,7 @@
 package org.oceandsl.tools.mop.stages;
 
 import org.oceandsl.architecture.model.ArchitectureModelManagementFactory;
-import org.oceandsl.tools.mop.operations.ModelRepositoryMerger;
+import org.oceandsl.tools.mop.merge.ModelRepositoryMerger;
 
 import kieker.analysis.stage.model.ModelRepository;
 import teetime.framework.AbstractConsumerStage;
@@ -40,6 +40,7 @@ public class ModelProcessor extends AbstractConsumerStage<ModelRepository> {
 
     @Override
     protected void execute(final ModelRepository element) throws Exception {
+        this.logger.info("Merging models {}", element.getName());
         ModelRepositoryMerger.perform(this.lastModel, element);
         this.task++;
     }
diff --git a/tools/mop/src/test/java/org/oceandsl/tools/mop/operations/ModelRepositoryMergerTest.java b/tools/mop/src/test/java/org/oceandsl/tools/mop/operations/ModelRepositoryMergerTest.java
index 91da482a29a72dafa98a63cb9ec91dbe3c3f48fc..3314be5fac1725905900f072e360b0ac18b8c030 100644
--- a/tools/mop/src/test/java/org/oceandsl/tools/mop/operations/ModelRepositoryMergerTest.java
+++ b/tools/mop/src/test/java/org/oceandsl/tools/mop/operations/ModelRepositoryMergerTest.java
@@ -19,6 +19,7 @@ import java.util.Map.Entry;
 
 import org.junit.Assert;
 import org.junit.Test;
+import org.oceandsl.tools.mop.merge.ModelRepositoryMerger;
 
 import kieker.analysis.stage.model.ModelRepository;
 import kieker.model.analysismodel.assembly.AssemblyComponent;
@@ -46,7 +47,7 @@ public class ModelRepositoryMergerTest {
 
     /**
      * Test method for
-     * {@link org.oceandsl.tools.mop.operations.ModelRepositoryMerger#perform(kieker.analysis.stage.model.ModelRepository, kieker.analysis.stage.model.ModelRepository, org.oceandsl.tools.mop.EStrategy)}.
+     * {@link org.oceandsl.tools.mop.merge.ModelRepositoryMerger#perform(kieker.analysis.stage.model.ModelRepository, kieker.analysis.stage.model.ModelRepository, org.oceandsl.tools.mop.EStrategy)}.
      */
     @Test
     public void testPerformType() {
diff --git a/tools/mvis/build.gradle b/tools/mvis/build.gradle
index d068080e90302fd96fb0ca349b23e2107b055c73..51d5232bbebd6265626c49094272faa600554c16 100644
--- a/tools/mvis/build.gradle
+++ b/tools/mvis/build.gradle
@@ -26,6 +26,7 @@ dependencies {
     implementation 'jakarta.xml.bind:jakarta.xml.bind-api:2.3.3'
     implementation 'com.sun.xml.bind:jaxb-impl:2.3.3'
     implementation 'org.apache.commons:commons-compress:1.20'
+    implementation 'org.mosim.refactorlizar:architecture-evaluation-tool:0.0.4'
 }
 
 application {
diff --git a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/GraphGenerationConverter.java b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/GraphGenerationConverter.java
new file mode 100644
index 0000000000000000000000000000000000000000..c4c1e16d08f95337207079e481b4c2a28ad859d0
--- /dev/null
+++ b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/GraphGenerationConverter.java
@@ -0,0 +1,38 @@
+/***************************************************************************
+ * Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
+package org.oceandsl.tools.mvis;
+
+import com.beust.jcommander.IStringConverter;
+
+import org.oceandsl.tools.mvis.stages.graph.EGraphGenerationMode;
+
+/**
+ * @author reiner
+ *
+ */
+public class GraphGenerationConverter implements IStringConverter<EGraphGenerationMode> {
+
+    @Override
+    public EGraphGenerationMode convert(final String value) {
+        for (final EGraphGenerationMode mode : EGraphGenerationMode.values()) {
+            if (mode.getKey().equals(value)) {
+                return mode;
+            }
+        }
+        throw new IllegalArgumentException(String.format("Graph generation mode %s is not supported.", value));
+    }
+
+}
diff --git a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/ModelVisualizationMain.java b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/ModelVisualizationMain.java
index 4882c57ad095f29babae8a862501757f94075a7e..9b09f1cab9fb4893af7f19efa212d26d737b1598 100644
--- a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/ModelVisualizationMain.java
+++ b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/ModelVisualizationMain.java
@@ -21,11 +21,10 @@ import java.nio.file.Files;
 
 import com.beust.jcommander.JCommander;
 
-import org.oceandsl.architecture.model.ArchitectureModelManagementFactory;
 import org.oceandsl.architecture.model.data.table.ValueConversionErrorException;
+import org.oceandsl.tools.mvis.stages.graph.EGraphGenerationMode;
 import org.slf4j.LoggerFactory;
 
-import kieker.analysis.stage.model.ModelRepository;
 import kieker.common.configuration.Configuration;
 import kieker.common.exception.ConfigurationException;
 import kieker.tools.common.AbstractService;
@@ -38,8 +37,6 @@ import kieker.tools.common.AbstractService;
  */
 public class ModelVisualizationMain extends AbstractService<TeetimeConfiguration, Settings> {
 
-    private ModelRepository repository;
-
     public static void main(final String[] args) {
         final ModelVisualizationMain main = new ModelVisualizationMain();
         try {
@@ -55,9 +52,7 @@ public class ModelVisualizationMain extends AbstractService<TeetimeConfiguration
     @Override
     protected TeetimeConfiguration createTeetimeConfiguration() throws ConfigurationException {
         try {
-            this.repository = ArchitectureModelManagementFactory
-                    .loadModelRepository(this.parameterConfiguration.getInputDirectory());
-            return new TeetimeConfiguration(this.logger, this.parameterConfiguration, this.repository);
+            return new TeetimeConfiguration(this.logger, this.parameterConfiguration);
         } catch (final IOException | ValueConversionErrorException e) {
             this.logger.error("Error reading files. Cause: {}", e.getLocalizedMessage());
             throw new ConfigurationException(e);
@@ -77,6 +72,16 @@ public class ModelVisualizationMain extends AbstractService<TeetimeConfiguration
 
     @Override
     protected boolean checkParameters(final JCommander commander) throws ConfigurationException {
+        if (this.parameterConfiguration.getGraphGenerationMode() == null) {
+            this.logger.error("You need to specify a graph generation mode: {}",
+                    this.createModeList(EGraphGenerationMode.values()));
+            return false;
+        }
+        if (this.parameterConfiguration.getSelector() == null) {
+            this.logger.error("No valid node and edge selector specificed. Valid types are: {}",
+                    this.createSelectorList(ESelectorKind.values()));
+            return false;
+        }
         if (!Files.isDirectory(this.parameterConfiguration.getOutputDirectory())) {
             this.logger.error("Output path {} is not directory", this.parameterConfiguration.getOutputDirectory());
             return false;
@@ -88,6 +93,30 @@ public class ModelVisualizationMain extends AbstractService<TeetimeConfiguration
         return true;
     }
 
+    private Object createSelectorList(final ESelectorKind[] values) {
+        String list = null;
+        for (final ESelectorKind value : values) {
+            if (list == null) {
+                list = value.name().toLowerCase();
+            } else {
+                list += "," + value.name().toLowerCase();
+            }
+        }
+        return list;
+    }
+
+    private String createModeList(final EGraphGenerationMode[] values) {
+        String list = null;
+        for (final EGraphGenerationMode value : values) {
+            if (list == null) {
+                list = value.getKey();
+            } else {
+                list += "," + value.getKey();
+            }
+        }
+        return list;
+    }
+
     @Override
     protected void shutdownService() {
 
diff --git a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/Settings.java b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/Settings.java
index 809ce91519158c14bb3f1cb8808bb5ed71f51383..f72e875310555de0732a5584e685db1e5c1caccd 100644
--- a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/Settings.java
+++ b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/Settings.java
@@ -21,6 +21,7 @@ import java.util.List;
 import com.beust.jcommander.Parameter;
 import com.beust.jcommander.converters.PathConverter;
 
+import org.oceandsl.tools.mvis.stages.graph.EGraphGenerationMode;
 import org.oceandsl.tools.mvis.stages.graph.IGraphElementSelector;
 
 /**
@@ -51,6 +52,10 @@ public class Settings {
             "--graphs" }, required = false, variableArity = true, converter = GraphTypeConverter.class, description = "Specify which output graphs must be generated")
     private List<EOutputGraph> outputGraphs;
 
+    @Parameter(names = { "-m",
+            "--mode" }, required = true, variableArity = true, converter = GraphGenerationConverter.class, description = "Mode deciding whether an edge is added when its nodes are not selected")
+    private EGraphGenerationMode graphGenerationMode;
+
     public Path getInputDirectory() {
         return this.inputDirectory;
     }
@@ -70,4 +75,8 @@ public class Settings {
     public IGraphElementSelector getSelector() {
         return this.selector;
     }
+
+    public EGraphGenerationMode getGraphGenerationMode() {
+        return this.graphGenerationMode;
+    }
 }
diff --git a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/TeetimeConfiguration.java b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/TeetimeConfiguration.java
index 48777e794860ead67c95bf91b0de987bc12a460d..34306c7f3b27c52c5a5d0b45032cc202ea87242d 100644
--- a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/TeetimeConfiguration.java
+++ b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/TeetimeConfiguration.java
@@ -18,19 +18,19 @@ package org.oceandsl.tools.mvis;
 import java.io.IOException;
 
 import org.oceandsl.architecture.model.data.table.ValueConversionErrorException;
+import org.oceandsl.architecture.model.stages.ModelRepositoryProducerStage;
 import org.oceandsl.architecture.model.stages.sinks.TableCSVSink;
 import org.oceandsl.architecture.model.stages.utils.DedicatedFileNameMapper;
 import org.oceandsl.tools.mvis.graph.ColorAssemblyLevelComponentDependencyGraphBuilderFactory;
 import org.oceandsl.tools.mvis.graph.ColorAssemblyLevelOperationDependencyGraphBuilderFactory;
 import org.oceandsl.tools.mvis.graph.ColoredDotExportConfigurationFactory;
 import org.oceandsl.tools.mvis.graph.IColorDependencyGraphBuilderConfiguration;
-import org.oceandsl.tools.mvis.stages.ModelRepositoryProducerStage;
-import org.oceandsl.tools.mvis.stages.SaveAllenDataStage;
-import org.oceandsl.tools.mvis.stages.graph.AllenDeployedArchitectureGraphStage;
+import org.oceandsl.tools.mvis.stages.entropy.AllenDeployedArchitectureGraphStage;
+import org.oceandsl.tools.mvis.stages.entropy.ComputeAllenComplexityMetrics;
+import org.oceandsl.tools.mvis.stages.entropy.SaveAllenDataStage;
 import org.oceandsl.tools.mvis.stages.graph.ColorDependencyGraphBuilderConfiguration;
 import org.oceandsl.tools.mvis.stages.graph.ModuleCallGraphStage;
 import org.oceandsl.tools.mvis.stages.graph.OperationCallGraphStage;
-import org.oceandsl.tools.mvis.stages.metrics.ComputeAllenComplexityMetrics;
 import org.oceandsl.tools.mvis.stages.metrics.ModuleNodeCountCouplingStage;
 import org.oceandsl.tools.mvis.stages.metrics.NumberOfCallsStage;
 import org.oceandsl.tools.mvis.stages.metrics.OperationNodeCountCouplingStage;
@@ -43,8 +43,6 @@ import kieker.analysis.graph.export.graphml.GraphMLFileWriterStage;
 import kieker.analysis.graph.util.FileExtension;
 import kieker.analysis.signature.NameBuilder;
 import kieker.analysis.stage.model.ModelRepository;
-import kieker.analysis.util.stage.trigger.Trigger;
-import kieker.analysis.util.stage.trigger.TriggerOnTerminationStage;
 import teetime.framework.Configuration;
 import teetime.stage.basic.distributor.Distributor;
 import teetime.stage.basic.distributor.strategy.CopyByReferenceStrategy;
@@ -58,21 +56,18 @@ import teetime.stage.basic.distributor.strategy.CopyByReferenceStrategy;
 public class TeetimeConfiguration extends Configuration {
 
     private static final String OPERATION_CALLS_CSV = "operation-calls.csv";
-    private static final String DISTINCT_OPERATION_DEGREE_CSV = "distinct-operatin-degree.csv";
+    private static final String DISTINCT_OPERATION_DEGREE_CSV = "distinct-operation-degree.csv";
     private static final String DISTINCT_MODULE_DEGREE_CSV = "distinct-module-degree.csv";
 
-    public TeetimeConfiguration(final Logger logger, final Settings parameterConfiguration,
-            final ModelRepository repository) throws IOException, ValueConversionErrorException {
+    public TeetimeConfiguration(final Logger logger, final Settings settings)
+            throws IOException, ValueConversionErrorException {
 
-        final ModelRepositoryProducerStage readerStage = new ModelRepositoryProducerStage(
-                parameterConfiguration.getInputDirectory());
+        final ModelRepositoryProducerStage readerStage = new ModelRepositoryProducerStage(settings.getInputDirectory());
 
-        final TriggerOnTerminationStage triggerStage = new TriggerOnTerminationStage();
-        final Distributor<Trigger> triggerDistributor = new Distributor<>(new CopyByReferenceStrategy());
+        final Distributor<ModelRepository> triggerDistributor = new Distributor<>(new CopyByReferenceStrategy());
 
         final DotFileWriterStage dotFileOperationDependencyWriterStage = new DotFileWriterStage(
-                new DedicatedFileNameMapper(parameterConfiguration.getOutputDirectory(), "operation",
-                        FileExtension.DOT),
+                new DedicatedFileNameMapper(settings.getOutputDirectory(), "operation", FileExtension.DOT),
                 new ColoredDotExportConfigurationFactory(NameBuilder.forJavaShortOperations())
                         .createForAssemblyLevelOperationDependencyGraph(false));
 
@@ -80,37 +75,32 @@ public class TeetimeConfiguration extends Configuration {
 
         /** Stages for statistics. */
         final NumberOfCallsStage numberOfCallsStage = new NumberOfCallsStage();
-        final OperationCallGraphStage functionCallGraphStage = new OperationCallGraphStage(
-                parameterConfiguration.getSelector());
+        final OperationCallGraphStage functionCallGraphStage = new OperationCallGraphStage(settings.getSelector(),
+                settings.getGraphGenerationMode());
         final OperationNodeCountCouplingStage functionNodeCouplingStage = new OperationNodeCountCouplingStage();
-        final ModuleCallGraphStage moduleCallGraphStage = new ModuleCallGraphStage(
-                parameterConfiguration.getSelector());
+        final ModuleCallGraphStage moduleCallGraphStage = new ModuleCallGraphStage(settings.getSelector(),
+                settings.getGraphGenerationMode());
         final ModuleNodeCountCouplingStage moduleNodeCouplingStage = new ModuleNodeCountCouplingStage();
 
         /** Sinks for metrics writing to CSV files. */
-        final TableCSVSink operationCallSink = new TableCSVSink(parameterConfiguration.getOutputDirectory(),
-                String.format("%s-%s", parameterConfiguration.getSelector().getFilePrefix(),
-                        TeetimeConfiguration.OPERATION_CALLS_CSV));
-        final TableCSVSink distinctOperationDegreeSink = new TableCSVSink(parameterConfiguration.getOutputDirectory(),
-                String.format("%s-%s", parameterConfiguration.getSelector().getFilePrefix(),
-                        TeetimeConfiguration.DISTINCT_OPERATION_DEGREE_CSV));
-        final TableCSVSink distinctModuleDegreeSink = new TableCSVSink(parameterConfiguration.getOutputDirectory(),
-                String.format("%s-%s", parameterConfiguration.getSelector().getFilePrefix(),
-                        TeetimeConfiguration.DISTINCT_MODULE_DEGREE_CSV));
-
-        final GraphMLFileWriterStage graphMLFileWriterStage = new GraphMLFileWriterStage(
-                parameterConfiguration.getOutputDirectory());
+        final TableCSVSink operationCallSink = new TableCSVSink(settings.getOutputDirectory(), String.format("%s-%s",
+                settings.getSelector().getFilePrefix(), TeetimeConfiguration.OPERATION_CALLS_CSV));
+        final TableCSVSink distinctOperationDegreeSink = new TableCSVSink(settings.getOutputDirectory(), String.format(
+                "%s-%s", settings.getSelector().getFilePrefix(), TeetimeConfiguration.DISTINCT_OPERATION_DEGREE_CSV));
+        final TableCSVSink distinctModuleDegreeSink = new TableCSVSink(settings.getOutputDirectory(), String.format(
+                "%s-%s", settings.getSelector().getFilePrefix(), TeetimeConfiguration.DISTINCT_MODULE_DEGREE_CSV));
+
+        final GraphMLFileWriterStage graphMLFileWriterStage = new GraphMLFileWriterStage(settings.getOutputDirectory());
 
         /** connecting ports. */
-        this.connectPorts(statisticsDistributor.getNewOutputPort(), triggerStage.getInputPort());
-        this.connectPorts(triggerStage.getOutputPort(), triggerDistributor.getInputPort());
+        this.connectPorts(statisticsDistributor.getNewOutputPort(), triggerDistributor.getInputPort());
 
         final IColorDependencyGraphBuilderConfiguration configuration = new ColorDependencyGraphBuilderConfiguration(
-                repository, parameterConfiguration.getSelector());
+                settings.getSelector());
 
         /** operation graph. */
-        if (parameterConfiguration.getOutputGraphs().contains(EOutputGraph.DOT_OP)
-                || parameterConfiguration.getOutputGraphs().contains(EOutputGraph.GRAPHML)) {
+        if (settings.getOutputGraphs().contains(EOutputGraph.DOT_OP)
+                || settings.getOutputGraphs().contains(EOutputGraph.GRAPHML)) {
             final DependencyGraphCreatorStage<IColorDependencyGraphBuilderConfiguration> operationDependencyGraphCreatorStage = new DependencyGraphCreatorStage<>(
                     configuration, new ColorAssemblyLevelOperationDependencyGraphBuilderFactory());
             final Distributor<IGraph> graphsDistributor = new Distributor<>(new CopyByReferenceStrategy());
@@ -118,22 +108,21 @@ public class TeetimeConfiguration extends Configuration {
             this.connectPorts(triggerDistributor.getNewOutputPort(),
                     operationDependencyGraphCreatorStage.getInputPort());
             this.connectPorts(operationDependencyGraphCreatorStage.getOutputPort(), graphsDistributor.getInputPort());
-            if (parameterConfiguration.getOutputGraphs().contains(EOutputGraph.DOT_OP)) {
+            if (settings.getOutputGraphs().contains(EOutputGraph.DOT_OP)) {
                 this.connectPorts(graphsDistributor.getNewOutputPort(),
                         dotFileOperationDependencyWriterStage.getInputPort());
             }
-            if (parameterConfiguration.getOutputGraphs().contains(EOutputGraph.GRAPHML)) {
+            if (settings.getOutputGraphs().contains(EOutputGraph.GRAPHML)) {
                 this.connectPorts(graphsDistributor.getNewOutputPort(), graphMLFileWriterStage.getInputPort());
             }
         }
 
         /** component graph. */
-        if (parameterConfiguration.getOutputGraphs().contains(EOutputGraph.DOT_COMPONENT)) {
+        if (settings.getOutputGraphs().contains(EOutputGraph.DOT_COMPONENT)) {
             final DependencyGraphCreatorStage<IColorDependencyGraphBuilderConfiguration> componentDependencyGraphCreatorStage = new DependencyGraphCreatorStage<>(
                     configuration, new ColorAssemblyLevelComponentDependencyGraphBuilderFactory());
             final DotFileWriterStage componentDependencyDotFileWriterStage = new DotFileWriterStage(
-                    new DedicatedFileNameMapper(parameterConfiguration.getOutputDirectory(), "component",
-                            FileExtension.DOT),
+                    new DedicatedFileNameMapper(settings.getOutputDirectory(), "component", FileExtension.DOT),
                     new ColoredDotExportConfigurationFactory(NameBuilder.forJavaShortOperations())
                             .createForAssemblyLevelComponentDependencyGraph(false));
 
@@ -145,10 +134,9 @@ public class TeetimeConfiguration extends Configuration {
 
         /** setup allen metrics. */
         final AllenDeployedArchitectureGraphStage allenArchitectureModularGraphStage = new AllenDeployedArchitectureGraphStage(
-                parameterConfiguration.getSelector());
+                settings.getSelector(), settings.getGraphGenerationMode());
         final ComputeAllenComplexityMetrics computeAllenComplexityStage = new ComputeAllenComplexityMetrics();
-        final SaveAllenDataStage saveAllenDataStage = new SaveAllenDataStage(
-                parameterConfiguration.getOutputDirectory());
+        final SaveAllenDataStage saveAllenDataStage = new SaveAllenDataStage(settings.getOutputDirectory());
 
         /** connect stages. */
         this.connectPorts(readerStage.getOutputPort(), statisticsDistributor.getInputPort());
diff --git a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/graph/AbstractColorDependencyGraphBuilder.java b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/graph/AbstractColorDependencyGraphBuilder.java
index f1bbadb2a10ba4799885fd1e7c90bb292b83cdd1..b1d7899890a70188c3dd7d8e62c8c599952955a4 100644
--- a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/graph/AbstractColorDependencyGraphBuilder.java
+++ b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/graph/AbstractColorDependencyGraphBuilder.java
@@ -15,6 +15,8 @@
  ***************************************************************************/
 package org.oceandsl.tools.mvis.graph;
 
+import java.time.temporal.ChronoUnit;
+
 import org.eclipse.emf.common.util.EList;
 import org.eclipse.emf.common.util.EMap;
 import org.eclipse.emf.ecore.EObject;
@@ -23,15 +25,19 @@ import org.oceandsl.tools.mvis.stages.graph.IGraphElementSelector;
 import kieker.analysis.graph.IGraph;
 import kieker.analysis.graph.IVertex;
 import kieker.analysis.graph.dependency.AbstractDependencyGraphBuilder;
+import kieker.analysis.graph.dependency.ResponseTimeDecorator;
 import kieker.analysis.stage.model.ModelRepository;
+import kieker.analysis.util.ObjectIdentifierRegistry;
 import kieker.model.analysismodel.deployment.DeployedStorage;
 import kieker.model.analysismodel.execution.AggregatedInvocation;
 import kieker.model.analysismodel.execution.AggregatedStorageAccess;
+import kieker.model.analysismodel.execution.ExecutionModel;
 import kieker.model.analysismodel.sources.SourceModel;
 import kieker.model.analysismodel.statistics.EPredefinedUnits;
 import kieker.model.analysismodel.statistics.EPropertyType;
 import kieker.model.analysismodel.statistics.StatisticRecord;
 import kieker.model.analysismodel.statistics.Statistics;
+import kieker.model.analysismodel.statistics.StatisticsModel;
 
 /**
  * @author Reiner Jung
@@ -40,12 +46,11 @@ import kieker.model.analysismodel.statistics.Statistics;
  */
 public abstract class AbstractColorDependencyGraphBuilder extends AbstractDependencyGraphBuilder {
 
-    private final SourceModel sourcesModel;
+    private SourceModel sourcesModel;
     private final IGraphElementSelector selector;
 
-    public AbstractColorDependencyGraphBuilder(final ModelRepository repository, final IGraphElementSelector selector) {
-        super(repository);
-        this.sourcesModel = repository.getModel(SourceModel.class);
+    public AbstractColorDependencyGraphBuilder(final IGraphElementSelector selector) {
+        super();
         this.selector = selector;
     }
 
@@ -84,7 +89,15 @@ public abstract class AbstractColorDependencyGraphBuilder extends AbstractDepend
     }
 
     @Override
-    public IGraph build() {
+    public IGraph build(final ModelRepository repository) {
+        this.graph = IGraph.create();
+        this.graph.setName(repository.getName());
+
+        this.sourcesModel = repository.getModel(SourceModel.class);
+        this.executionModel = repository.getModel(ExecutionModel.class);
+        this.statisticsModel = repository.getModel(StatisticsModel.class);
+        this.identifierRegistry = new ObjectIdentifierRegistry();
+        this.responseTimeDecorator = new ResponseTimeDecorator(this.statisticsModel, ChronoUnit.NANOS);
         for (final AggregatedInvocation invocation : this.executionModel.getAggregatedInvocations().values()) {
             this.handleInvocation(invocation);
         }
diff --git a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/graph/ColorAssemblyLevelComponentDependencyGraphBuilder.java b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/graph/ColorAssemblyLevelComponentDependencyGraphBuilder.java
index 70a9fdaba63471fde350eefa245960de953d09d6..d06dcb86c157239f20c0b9cde130a8d06abb5146 100644
--- a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/graph/ColorAssemblyLevelComponentDependencyGraphBuilder.java
+++ b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/graph/ColorAssemblyLevelComponentDependencyGraphBuilder.java
@@ -21,7 +21,6 @@ import org.oceandsl.tools.mvis.stages.graph.IGraphElementSelector;
 import kieker.analysis.graph.IVertex;
 import kieker.analysis.graph.dependency.PropertyConstants;
 import kieker.analysis.graph.dependency.vertextypes.VertexType;
-import kieker.analysis.stage.model.ModelRepository;
 import kieker.model.analysismodel.assembly.AssemblyComponent;
 import kieker.model.analysismodel.assembly.AssemblyOperation;
 import kieker.model.analysismodel.assembly.AssemblyStorage;
@@ -35,9 +34,8 @@ import kieker.model.analysismodel.deployment.DeployedStorage;
  */
 public class ColorAssemblyLevelComponentDependencyGraphBuilder extends AbstractColorDependencyGraphBuilder {
 
-    public ColorAssemblyLevelComponentDependencyGraphBuilder(final ModelRepository repository,
-            final IGraphElementSelector selector) {
-        super(repository, selector);
+    public ColorAssemblyLevelComponentDependencyGraphBuilder(final IGraphElementSelector selector) {
+        super(selector);
     }
 
     @Override
diff --git a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/graph/ColorAssemblyLevelComponentDependencyGraphBuilderFactory.java b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/graph/ColorAssemblyLevelComponentDependencyGraphBuilderFactory.java
index 8eea6236aaf316332474a32897f84ec0944e720a..765bbd5f8a59c2a35afb9554942b73f6bb892eaf 100644
--- a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/graph/ColorAssemblyLevelComponentDependencyGraphBuilderFactory.java
+++ b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/graph/ColorAssemblyLevelComponentDependencyGraphBuilderFactory.java
@@ -33,8 +33,7 @@ public class ColorAssemblyLevelComponentDependencyGraphBuilderFactory
     @Override
     public IDependencyGraphBuilder createDependencyGraphBuilder(
             final IColorDependencyGraphBuilderConfiguration configuration) {
-        return new ColorAssemblyLevelComponentDependencyGraphBuilder(configuration.getModelRepository(),
-                configuration.getSelector());
+        return new ColorAssemblyLevelComponentDependencyGraphBuilder(configuration.getSelector());
     }
 
 }
diff --git a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/graph/ColorAssemblyLevelOperationDependencyGraphBuilder.java b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/graph/ColorAssemblyLevelOperationDependencyGraphBuilder.java
index b15872a035475f914ac4108122dad3c0f39653eb..6ad9c37701cc75e4d7375648c32d9218d3e5f3c2 100644
--- a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/graph/ColorAssemblyLevelOperationDependencyGraphBuilder.java
+++ b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/graph/ColorAssemblyLevelOperationDependencyGraphBuilder.java
@@ -38,14 +38,13 @@ import kieker.model.analysismodel.deployment.DeployedStorage;
  */
 public class ColorAssemblyLevelOperationDependencyGraphBuilder extends AbstractColorDependencyGraphBuilder {
 
-    public ColorAssemblyLevelOperationDependencyGraphBuilder(final ModelRepository repository,
-            final IGraphElementSelector selector) {
-        super(repository, selector);
+    public ColorAssemblyLevelOperationDependencyGraphBuilder(final IGraphElementSelector selector) {
+        super(selector);
     }
 
     @Override
-    public IGraph build() {
-        return super.build();
+    public IGraph build(final ModelRepository repository) {
+        return super.build(repository);
     }
 
     @Override
diff --git a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/graph/ColorAssemblyLevelOperationDependencyGraphBuilderFactory.java b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/graph/ColorAssemblyLevelOperationDependencyGraphBuilderFactory.java
index a546c69f11246f6323f1421c52afc5dcbc98b387..55aec13702d594107794ae47081bda30d91c8e18 100644
--- a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/graph/ColorAssemblyLevelOperationDependencyGraphBuilderFactory.java
+++ b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/graph/ColorAssemblyLevelOperationDependencyGraphBuilderFactory.java
@@ -34,8 +34,7 @@ public class ColorAssemblyLevelOperationDependencyGraphBuilderFactory
     @Override
     public IDependencyGraphBuilder createDependencyGraphBuilder(
             final IColorDependencyGraphBuilderConfiguration configuration) {
-        return new ColorAssemblyLevelOperationDependencyGraphBuilder(configuration.getModelRepository(),
-                configuration.getSelector());
+        return new ColorAssemblyLevelOperationDependencyGraphBuilder(configuration.getSelector());
     }
 
 }
diff --git a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/AllenDeployedArchitectureGraphStage.java b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/entropy/AllenDeployedArchitectureGraphStage.java
similarity index 61%
rename from tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/AllenDeployedArchitectureGraphStage.java
rename to tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/entropy/AllenDeployedArchitectureGraphStage.java
index fb21bda2cf019685be7ca868e3e2c349d1beefe1..1e7217638a4281f1578529af0144e3e3d5f4cc2c 100644
--- a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/AllenDeployedArchitectureGraphStage.java
+++ b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/entropy/AllenDeployedArchitectureGraphStage.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  ***************************************************************************/
-package org.oceandsl.tools.mvis.stages.graph;
+package org.oceandsl.tools.mvis.stages.entropy;
 
 import java.util.Map.Entry;
 
@@ -21,9 +21,11 @@ import com.google.common.graph.Graph;
 import com.google.common.graph.GraphBuilder;
 import com.google.common.graph.MutableGraph;
 
-import org.oceandsl.architecture.model.stages.utils.RepositoryUtils;
+import org.mosim.refactorlizar.architecture.evaluation.graphs.Node;
+import org.oceandsl.tools.mvis.stages.graph.EGraphGenerationMode;
+import org.oceandsl.tools.mvis.stages.graph.IGraphElementSelector;
+import org.oceandsl.tools.mvis.stages.graph.KiekerNode;
 
-import edu.kit.kastel.sdq.case4lang.refactorlizar.architecture_evaluation.graphs.Node;
 import kieker.analysis.stage.model.ModelRepository;
 import kieker.model.analysismodel.deployment.DeployedComponent;
 import kieker.model.analysismodel.deployment.DeployedOperation;
@@ -32,7 +34,6 @@ import kieker.model.analysismodel.deployment.DeploymentModel;
 import kieker.model.analysismodel.execution.AggregatedInvocation;
 import kieker.model.analysismodel.execution.ExecutionModel;
 import kieker.model.analysismodel.execution.Tuple;
-import kieker.model.analysismodel.sources.SourceModel;
 import teetime.stage.basic.AbstractTransformation;
 
 /**
@@ -42,10 +43,13 @@ import teetime.stage.basic.AbstractTransformation;
 public class AllenDeployedArchitectureGraphStage
         extends AbstractTransformation<ModelRepository, Graph<Node<DeployedComponent>>> {
 
-    IGraphElementSelector selector;
+    private final IGraphElementSelector selector;
+    private final EGraphGenerationMode graphGeneratioMode;
 
-    public AllenDeployedArchitectureGraphStage(final IGraphElementSelector selector) {
+    public AllenDeployedArchitectureGraphStage(final IGraphElementSelector selector,
+            final EGraphGenerationMode graphGeneratioMode) {
         this.selector = selector;
+        this.graphGeneratioMode = graphGeneratioMode;
     }
 
     @Override
@@ -64,12 +68,6 @@ public class AllenDeployedArchitectureGraphStage
                     if (this.selector.nodeIsSelected(operation.getValue())) {
                         final Node<DeployedComponent> node = new KiekerNode<>(operation.getValue());
                         graph.addNode(node);
-                    } else {
-                        this.logger.error("Node was skipped {}", RepositoryUtils.getName(operation.getValue()));
-                        final SourceModel sourceModel = repository.getModel(SourceModel.class);
-                        for (final String source : sourceModel.getSources().get(operation.getValue())) {
-                            this.logger.error("Node label: {}", source);
-                        }
                     }
                 }
             }
@@ -79,36 +77,34 @@ public class AllenDeployedArchitectureGraphStage
             if (this.selector.edgeIsSelected(entry.getValue())) {
                 final Node<DeployedComponent> source = this.findNode(graph, entry.getValue().getSource());
                 final Node<DeployedComponent> target = this.findNode(graph, entry.getValue().getTarget());
-                if (source != null && target != null) {
-                    graph.putEdge(source, target);
-                } else {
-                    final SourceModel sourceModel = repository.getModel(SourceModel.class);
-                    for (final String s : sourceModel.getSources().get(entry.getValue().getSource())) {
-                        this.logger.error("Source label: {}", s);
-                    }
-                    for (final String s : sourceModel.getSources().get(entry.getValue().getTarget())) {
-                        this.logger.error("Target label: {}", s);
-                    }
-                    for (final String s : sourceModel.getSources().get(entry.getValue())) {
-                        this.logger.error("Edge label: {}", s);
-                    }
 
-                    if (this.selector.nodeIsSelected(entry.getValue().getSource())
-                            && this.selector.nodeIsSelected(entry.getValue().getTarget())) {
-                        this.logger.error("Both nodes should be part of the graph, but are not: {} -> {}",
-                                RepositoryUtils.getName(entry.getValue().getSource()),
-                                RepositoryUtils.getName(entry.getValue().getTarget()));
-                    } else {
-                        this.logger.warn("When an edge is selected, both nodes should be selected too: {} -> {}",
-                                RepositoryUtils.getName(entry.getValue().getSource()),
-                                RepositoryUtils.getName(entry.getValue().getTarget()));
+                switch (this.graphGeneratioMode) {
+                case ADD_NODES_FOR_EDGES:
+                    graph.putEdge(this.getOrCreateNode(graph, source, entry.getValue().getSource()),
+                            this.getOrCreateNode(graph, target, entry.getValue().getTarget()));
+                    break;
+                case ONLY_EDGES_FOR_NODES:
+                    if (source != null && target != null) {
+                        graph.putEdge(source, target);
                     }
+                    break;
                 }
             }
         }
         this.outputPort.send(graph);
     }
 
+    private Node<DeployedComponent> getOrCreateNode(final MutableGraph<Node<DeployedComponent>> graph,
+            final Node<DeployedComponent> node, final DeployedOperation operation) {
+        if (node == null) {
+            final Node<DeployedComponent> newNode = new KiekerNode<>(operation);
+            graph.addNode(newNode);
+            return newNode;
+        } else {
+            return node;
+        }
+    }
+
     private Node<DeployedComponent> findNode(final Graph<Node<DeployedComponent>> graph,
             final DeployedOperation operation) {
         for (final Node<DeployedComponent> node : graph.nodes()) {
@@ -119,8 +115,6 @@ public class AllenDeployedArchitectureGraphStage
             }
         }
 
-        this.logger.error("Internal error: Looked for node of an edge that does not exist: {}",
-                operation.getAssemblyOperation().getOperationType().getSignature());
         return null;
     }
 
diff --git a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/metrics/ComputeAllenComplexityMetrics.java b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/entropy/ComputeAllenComplexityMetrics.java
similarity index 59%
rename from tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/metrics/ComputeAllenComplexityMetrics.java
rename to tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/entropy/ComputeAllenComplexityMetrics.java
index 54d69c7c5944045ad600c4304db7d9c2bd2f9092..45678ee3b0f62ef8ce9f516344e90c29db49d2cd 100644
--- a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/metrics/ComputeAllenComplexityMetrics.java
+++ b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/entropy/ComputeAllenComplexityMetrics.java
@@ -13,21 +13,27 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  ***************************************************************************/
-package org.oceandsl.tools.mvis.stages.metrics;
+package org.oceandsl.tools.mvis.stages.entropy;
 
 import java.util.HashMap;
 import java.util.Map;
 
 import com.google.common.graph.Graph;
 
-import edu.kit.kastel.sdq.case4lang.refactorlizar.architecture_evaluation.CalculationMode;
-import edu.kit.kastel.sdq.case4lang.refactorlizar.architecture_evaluation.codemetrics.CodeMetric;
-import edu.kit.kastel.sdq.case4lang.refactorlizar.architecture_evaluation.codemetrics.Complexity;
-import edu.kit.kastel.sdq.case4lang.refactorlizar.architecture_evaluation.codemetrics.HyperGraphSize;
-import edu.kit.kastel.sdq.case4lang.refactorlizar.architecture_evaluation.complexity.HyperGraphComplexityCalculator;
-import edu.kit.kastel.sdq.case4lang.refactorlizar.architecture_evaluation.graphs.Node;
-import edu.kit.kastel.sdq.case4lang.refactorlizar.architecture_evaluation.graphs.SystemGraphUtils;
-import edu.kit.kastel.sdq.case4lang.refactorlizar.architecture_evaluation.size.HyperGraphSizeCalculator;
+import org.mosim.refactorlizar.architecture.evaluation.CalculationMode;
+import org.mosim.refactorlizar.architecture.evaluation.codemetrics.CodeMetric;
+import org.mosim.refactorlizar.architecture.evaluation.codemetrics.Cohesion;
+import org.mosim.refactorlizar.architecture.evaluation.codemetrics.Complexity;
+import org.mosim.refactorlizar.architecture.evaluation.codemetrics.Coupling;
+import org.mosim.refactorlizar.architecture.evaluation.codemetrics.HyperGraphSize;
+import org.mosim.refactorlizar.architecture.evaluation.cohesion.HyperGraphCohesionCalculator;
+import org.mosim.refactorlizar.architecture.evaluation.complexity.HyperGraphComplexityCalculator;
+import org.mosim.refactorlizar.architecture.evaluation.coupling.HyperGraphInterModuleCouplingGenerator;
+import org.mosim.refactorlizar.architecture.evaluation.graphs.Node;
+import org.mosim.refactorlizar.architecture.evaluation.graphs.SystemGraphUtils;
+import org.mosim.refactorlizar.architecture.evaluation.size.HyperGraphSizeCalculator;
+import org.oceandsl.tools.mvis.stages.metrics.KiekerArchitectureModelSystemGraphUtils;
+
 import kieker.model.analysismodel.deployment.DeployedComponent;
 import teetime.stage.basic.AbstractTransformation;
 
@@ -40,23 +46,21 @@ public class ComputeAllenComplexityMetrics
 
     @Override
     protected void execute(final Graph<Node<DeployedComponent>> graph) throws Exception {
-        final CalculationMode mode = CalculationMode.REINER;
+        final CalculationMode mode = CalculationMode.NO_OFFSET;
         final SystemGraphUtils<DeployedComponent> systemGraphUtils = new KiekerArchitectureModelSystemGraphUtils();
 
         final HyperGraphSize size = this.calculateHyperGraphSize(mode, systemGraphUtils, graph);
         final Complexity graphComplexity = new HyperGraphComplexityCalculator<>(mode, systemGraphUtils)
                 .calculate(graph);
-        // final Coupling graphCoupling = new HyperGraphInterModuleCouplingGenerator<>(mode,
-        // systemGraphUtils)
-        // .calculate(graph);
-        // final Cohesion cohesion = new HyperGraphCohesionCalculator<>(mode,
-        // systemGraphUtils).calculate(graph);
+        final Coupling graphCoupling = new HyperGraphInterModuleCouplingGenerator<>(mode, systemGraphUtils)
+                .calculate(graph);
+        final Cohesion cohesion = new HyperGraphCohesionCalculator<>(mode, systemGraphUtils).calculate(graph);
 
         final Map<Class<? extends CodeMetric>, CodeMetric> result = new HashMap<>();
         result.put(HyperGraphSize.class, size);
         result.put(Complexity.class, graphComplexity);
-        // result.put(Coupling.class, graphCoupling);
-        // result.put(Cohesion.class, cohesion);
+        result.put(Coupling.class, graphCoupling);
+        result.put(Cohesion.class, cohesion);
 
         this.outputPort.send(result);
     }
diff --git a/tools/create-architecture-model/src/main/java/org/oceandsl/architecture/model/stages/sinks/ResultSink.java b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/entropy/EntropyResultSink.java
similarity index 86%
rename from tools/create-architecture-model/src/main/java/org/oceandsl/architecture/model/stages/sinks/ResultSink.java
rename to tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/entropy/EntropyResultSink.java
index e3cfee97902ab4c496c177cc4988e78e6bc8b084..95e7eb37aa20824881c630a93713a96610e86aaf 100644
--- a/tools/create-architecture-model/src/main/java/org/oceandsl/architecture/model/stages/sinks/ResultSink.java
+++ b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/entropy/EntropyResultSink.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  ***************************************************************************/
-package org.oceandsl.architecture.model.stages.sinks;
+package org.oceandsl.tools.mvis.stages.entropy;
 
 import java.io.BufferedWriter;
 import java.io.IOException;
@@ -24,19 +24,20 @@ import java.nio.file.StandardOpenOption;
 import java.util.Map;
 import java.util.Map.Entry;
 
-import edu.kit.kastel.sdq.case4lang.refactorlizar.architecture_evaluation.codemetrics.CodeMetric;
+import org.mosim.refactorlizar.architecture.evaluation.codemetrics.CodeMetric;
+
 import teetime.framework.AbstractConsumerStage;
 
 /**
  * @author Reiner Jung
  *
  */
-public class ResultSink extends AbstractConsumerStage<Map<Class<? extends CodeMetric>, CodeMetric>> {
+public class EntropyResultSink extends AbstractConsumerStage<Map<Class<? extends CodeMetric>, CodeMetric>> {
 
     private final BufferedWriter fileHandle;
     private final Path path;
 
-    public ResultSink(final Path path) throws IOException {
+    public EntropyResultSink(final Path path) throws IOException {
         this.fileHandle = Files.newBufferedWriter(path, StandardCharsets.UTF_8, StandardOpenOption.CREATE,
                 StandardOpenOption.WRITE);
         this.path = path;
diff --git a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/SaveAllenDataStage.java b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/entropy/SaveAllenDataStage.java
similarity index 93%
rename from tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/SaveAllenDataStage.java
rename to tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/entropy/SaveAllenDataStage.java
index abb9a78afdd69e4ae2f5aae25d19858ebda5fad0..40e1d73a3ce56e15a8c692c4462b72bda215ca1e 100644
--- a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/SaveAllenDataStage.java
+++ b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/entropy/SaveAllenDataStage.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  ***************************************************************************/
-package org.oceandsl.tools.mvis.stages;
+package org.oceandsl.tools.mvis.stages.entropy;
 
 import java.io.BufferedWriter;
 import java.nio.file.Files;
@@ -21,7 +21,8 @@ import java.nio.file.Path;
 import java.util.Map;
 import java.util.Map.Entry;
 
-import edu.kit.kastel.sdq.case4lang.refactorlizar.architecture_evaluation.codemetrics.CodeMetric;
+import org.mosim.refactorlizar.architecture.evaluation.codemetrics.CodeMetric;
+
 import teetime.framework.AbstractConsumerStage;
 
 /**
diff --git a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/entropy/package-info.java b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/entropy/package-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..915625566d32b3d1dac675f91d5d7daa04feba8e
--- /dev/null
+++ b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/entropy/package-info.java
@@ -0,0 +1,20 @@
+/***************************************************************************
+ * Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
+/**
+ * @author Reiner Jung
+ * @since 1.0
+ */
+package org.oceandsl.tools.mvis.stages.entropy;
\ No newline at end of file
diff --git a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/ColorDependencyGraphBuilderConfiguration.java b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/ColorDependencyGraphBuilderConfiguration.java
index 8aba89084eb4e8debc1ff9498e1e4b40f381cdc8..bf22808c7c348d4723e6a3622fcd892b44f9d523 100644
--- a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/ColorDependencyGraphBuilderConfiguration.java
+++ b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/ColorDependencyGraphBuilderConfiguration.java
@@ -17,27 +17,19 @@ package org.oceandsl.tools.mvis.stages.graph;
 
 import org.oceandsl.tools.mvis.graph.IColorDependencyGraphBuilderConfiguration;
 
-import kieker.analysis.stage.model.ModelRepository;
-
 /**
- * @author reiner
+ * @author Reiner Jung
+ * @since 1.1
  *
  */
 public class ColorDependencyGraphBuilderConfiguration implements IColorDependencyGraphBuilderConfiguration {
 
-    private final ModelRepository modelRepository;
     private final IGraphElementSelector selector;
 
-    public ColorDependencyGraphBuilderConfiguration(final ModelRepository modelRepository, final IGraphElementSelector selector) {
-        this.modelRepository = modelRepository;
+    public ColorDependencyGraphBuilderConfiguration(final IGraphElementSelector selector) {
         this.selector = selector;
     }
 
-    @Override
-    public ModelRepository getModelRepository() {
-        return this.modelRepository;
-    }
-
     @Override
     public IGraphElementSelector getSelector() {
         return this.selector;
diff --git a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/CreateGraph4AllenMetricStage.java b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/CreateGraph4AllenMetricStage.java
index 85f15f910244d84c5b96ca8420ce648740194ca5..e5e8cd53ada0d41c847d1dd606314f8900d29d2d 100644
--- a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/CreateGraph4AllenMetricStage.java
+++ b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/CreateGraph4AllenMetricStage.java
@@ -22,7 +22,8 @@ import com.google.common.graph.Graph;
 import com.google.common.graph.GraphBuilder;
 import com.google.common.graph.MutableGraph;
 
-import edu.kit.kastel.sdq.case4lang.refactorlizar.architecture_evaluation.graphs.Node;
+import org.mosim.refactorlizar.architecture.evaluation.graphs.Node;
+
 import kieker.analysis.stage.model.ModelRepository;
 import kieker.model.analysismodel.deployment.DeployedComponent;
 import kieker.model.analysismodel.deployment.DeployedOperation;
@@ -41,6 +42,10 @@ import teetime.stage.basic.AbstractTransformation;
 public class CreateGraph4AllenMetricStage
         extends AbstractTransformation<ModelRepository, Graph<Node<DeployedComponent>>> {
 
+    public CreateGraph4AllenMetricStage() {
+        // TODO Auto-generated constructor stub
+    }
+
     @Override
     protected void execute(final ModelRepository element) throws Exception {
         final Graph<Node<DeployedComponent>> graph = this.computeGraph(element);
diff --git a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/EGraphGenerationMode.java b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/EGraphGenerationMode.java
new file mode 100644
index 0000000000000000000000000000000000000000..eddab86075188aceb561479c845196a9a450d134
--- /dev/null
+++ b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/EGraphGenerationMode.java
@@ -0,0 +1,40 @@
+/***************************************************************************
+ * Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
+package org.oceandsl.tools.mvis.stages.graph;
+
+/**
+ * Node and edge selection modes for graph construction.
+ *
+ * @author Reiner Jung
+ * @since 1.1
+ *
+ */
+public enum EGraphGenerationMode {
+    ADD_NODES_FOR_EDGES("add-nodes"), // add nodes when the edge should be included in the graph
+                                      // even if they are
+    // not selected
+    ONLY_EDGES_FOR_NODES("only"); // only add edges when nodes are already present
+
+    private final String key;
+
+    private EGraphGenerationMode(final String key) {
+        this.key = key;
+    }
+
+    public String getKey() {
+        return this.key;
+    }
+}
diff --git a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/KiekerNode.java b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/KiekerNode.java
index 06e5495e170974a952ad86ca14bbb30d3aaff59a..c6d344361e5088939c78da4134e2d62becf7ae40 100644
--- a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/KiekerNode.java
+++ b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/KiekerNode.java
@@ -18,8 +18,7 @@ package org.oceandsl.tools.mvis.stages.graph;
 import java.util.Objects;
 
 import org.eclipse.emf.ecore.EObject;
-
-import edu.kit.kastel.sdq.case4lang.refactorlizar.architecture_evaluation.graphs.Node;
+import org.mosim.refactorlizar.architecture.evaluation.graphs.Node;
 
 /**
  * Central node class for graphs
diff --git a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/ModuleCallGraphStage.java b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/ModuleCallGraphStage.java
index 8f81bed24f1c5ea40bcc4e2c5a943b6f9fc3d9b5..8184a2408af6745778b2b25b4c5f6cfcce01caa2 100644
--- a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/ModuleCallGraphStage.java
+++ b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/ModuleCallGraphStage.java
@@ -31,9 +31,11 @@ import teetime.stage.basic.AbstractTransformation;
 public class ModuleCallGraphStage extends AbstractTransformation<ModelRepository, IGraph> {
 
     private final IGraphElementSelector selector;
+    private final EGraphGenerationMode graphGeneratioMode;
 
-    public ModuleCallGraphStage(final IGraphElementSelector selector) {
+    public ModuleCallGraphStage(final IGraphElementSelector selector, final EGraphGenerationMode graphGeneratioMode) {
         this.selector = selector;
+        this.graphGeneratioMode = graphGeneratioMode;
     }
 
     @Override
@@ -52,9 +54,25 @@ public class ModuleCallGraphStage extends AbstractTransformation<ModelRepository
             if (targetSelected) {
                 graph.addVertexIfAbsent(invocation.getTarget().getComponent());
             }
-            if (sourceSelected && targetSelected && this.selector.edgeIsSelected(invocation)) {
-                graph.addEdge(invocation, graph.getVertex(invocation.getSource().getComponent()),
-                        graph.getVertex(invocation.getTarget().getComponent()));
+            switch (this.graphGeneratioMode) {
+            case ONLY_EDGES_FOR_NODES:
+                if (sourceSelected && targetSelected && this.selector.edgeIsSelected(invocation)) {
+                    graph.addEdge(invocation, graph.getVertex(invocation.getSource().getComponent()),
+                            graph.getVertex(invocation.getTarget().getComponent()));
+                }
+                break;
+            case ADD_NODES_FOR_EDGES:
+                if (this.selector.edgeIsSelected(invocation)) {
+                    if (!sourceSelected) {
+                        graph.addVertexIfAbsent(invocation.getSource().getComponent());
+                    }
+                    if (!targetSelected) {
+                        graph.addVertexIfAbsent(invocation.getTarget().getComponent());
+                    }
+                    graph.addEdge(invocation, graph.getVertex(invocation.getSource().getComponent()),
+                            graph.getVertex(invocation.getTarget().getComponent()));
+                }
+                break;
             }
         }
 
diff --git a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/OperationCallGraphStage.java b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/OperationCallGraphStage.java
index fa354a4458b394760fceea39e84bb61f2e9aac1a..07e3c9c6f9f35841de459a82bbead6bb4af0852d 100644
--- a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/OperationCallGraphStage.java
+++ b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/graph/OperationCallGraphStage.java
@@ -30,9 +30,12 @@ import teetime.stage.basic.AbstractTransformation;
 public class OperationCallGraphStage extends AbstractTransformation<ModelRepository, IGraph> {
 
     private final IGraphElementSelector selector;
+    private final EGraphGenerationMode graphGeneratioMode;
 
-    public OperationCallGraphStage(final IGraphElementSelector selector) {
+    public OperationCallGraphStage(final IGraphElementSelector selector,
+            final EGraphGenerationMode graphGeneratioMode) {
         this.selector = selector;
+        this.graphGeneratioMode = graphGeneratioMode;
     }
 
     @Override
@@ -51,9 +54,25 @@ public class OperationCallGraphStage extends AbstractTransformation<ModelReposit
             if (targetSelected) {
                 graph.addVertexIfAbsent(invocation.getTarget());
             }
-            if (sourceSelected && targetSelected && this.selector.edgeIsSelected(invocation)) {
-                graph.addEdge(invocation, graph.getVertex(invocation.getSource()),
-                        graph.getVertex(invocation.getTarget()));
+            switch (this.graphGeneratioMode) {
+            case ONLY_EDGES_FOR_NODES:
+                if (sourceSelected && targetSelected && this.selector.edgeIsSelected(invocation)) {
+                    graph.addEdge(invocation, graph.getVertex(invocation.getSource()),
+                            graph.getVertex(invocation.getTarget()));
+                }
+                break;
+            case ADD_NODES_FOR_EDGES:
+                if (this.selector.edgeIsSelected(invocation)) {
+                    if (!sourceSelected) {
+                        graph.addVertexIfAbsent(invocation.getSource());
+                    }
+                    if (!targetSelected) {
+                        graph.addVertexIfAbsent(invocation.getTarget());
+                    }
+                    graph.addEdge(invocation, graph.getVertex(invocation.getSource()),
+                            graph.getVertex(invocation.getTarget()));
+                }
+                break;
             }
         }
 
diff --git a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/metrics/KiekerArchitectureModelSystemGraphUtils.java b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/metrics/KiekerArchitectureModelSystemGraphUtils.java
index 8787c283436c6ad4275ad20f7e6906712d2daf4f..f5fc592106f94734c3effa92d82dadf02a90616f 100644
--- a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/metrics/KiekerArchitectureModelSystemGraphUtils.java
+++ b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/metrics/KiekerArchitectureModelSystemGraphUtils.java
@@ -19,10 +19,10 @@ import com.google.common.graph.Graph;
 import com.google.common.graph.Graphs;
 import com.google.common.graph.MutableGraph;
 
+import org.mosim.refactorlizar.architecture.evaluation.graphs.Node;
+import org.mosim.refactorlizar.architecture.evaluation.graphs.SystemGraphUtils;
 import org.oceandsl.tools.mvis.stages.graph.KiekerNode;
 
-import edu.kit.kastel.sdq.case4lang.refactorlizar.architecture_evaluation.graphs.Node;
-import edu.kit.kastel.sdq.case4lang.refactorlizar.architecture_evaluation.graphs.SystemGraphUtils;
 import kieker.model.analysismodel.deployment.DeployedComponent;
 import kieker.model.analysismodel.deployment.DeployedOperation;
 
diff --git a/tools/relabel/build.gradle b/tools/relabel/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..a030bd27e2bc4f082d695a13cd0a6dd130fdf629
--- /dev/null
+++ b/tools/relabel/build.gradle
@@ -0,0 +1,34 @@
+/*
+ * This file was generated by the Gradle 'init' task.
+ *
+ * This generated file contains a sample Java project to get you started.
+ * For more details take a look at the Java Quickstart chapter in the Gradle
+ * User Manual available at https://docs.gradle.org/6.5/userguide/tutorial_java_projects.html
+ */
+
+plugins {
+    id 'java'
+    id 'application'
+}
+
+dependencies {
+    implementation project(':common')
+    implementation project(':analysis')
+    implementation project(':tools:create-architecture-model')
+    
+    // https://mvnrepository.com/artifact/org.eclipse.emf/org.eclipse.emf.ecore
+    implementation 'org.eclipse.emf:org.eclipse.emf.ecore:2.23.0'
+    implementation 'org.eclipse.emf:org.eclipse.emf.ecore.xmi:2.16.0'
+    
+//    runtime 'org.eclipse.emf:org.eclipse.emf.ecore:2.23.0'
+    
+    implementation 'com.fasterxml.jackson.core:jackson-databind:2.12.0'
+    
+    implementation 'jakarta.xml.bind:jakarta.xml.bind-api:2.3.3'
+    implementation 'com.sun.xml.bind:jaxb-impl:2.3.3'
+    implementation 'org.apache.commons:commons-compress:1.20'
+}
+
+application {
+    mainClassName = 'org.oceandsl.tools.relable.RelabelSourceMain'
+}
diff --git a/tools/relabel/src/main/java/org/oceandsl/tools/relable/ModelRepositoryWriterStage.java b/tools/relabel/src/main/java/org/oceandsl/tools/relable/ModelRepositoryWriterStage.java
new file mode 100644
index 0000000000000000000000000000000000000000..a1151b232794611ba04266f6f99c1d83eda7d4eb
--- /dev/null
+++ b/tools/relabel/src/main/java/org/oceandsl/tools/relable/ModelRepositoryWriterStage.java
@@ -0,0 +1,45 @@
+/***************************************************************************
+ * Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
+package org.oceandsl.tools.relable;
+
+import java.nio.file.Path;
+
+import org.oceandsl.architecture.model.ArchitectureModelManagementFactory;
+
+import kieker.analysis.stage.model.ModelRepository;
+import teetime.framework.AbstractConsumerStage;
+
+/**
+ * Write model to repository.
+ *
+ * @author Reiner Jung
+ * @since 1.1
+ *
+ */
+public class ModelRepositoryWriterStage extends AbstractConsumerStage<ModelRepository> {
+
+    private final Path outputDirectory;
+
+    public ModelRepositoryWriterStage(final Path outputDirectory) {
+        this.outputDirectory = outputDirectory;
+    }
+
+    @Override
+    protected void execute(final ModelRepository element) throws Exception {
+        ArchitectureModelManagementFactory.writeModelRepository(this.outputDirectory, element);
+    }
+
+}
diff --git a/tools/relabel/src/main/java/org/oceandsl/tools/relable/RelabelSourceMain.java b/tools/relabel/src/main/java/org/oceandsl/tools/relable/RelabelSourceMain.java
new file mode 100644
index 0000000000000000000000000000000000000000..5f65146d80848faf345d408e068e16c7853832db
--- /dev/null
+++ b/tools/relabel/src/main/java/org/oceandsl/tools/relable/RelabelSourceMain.java
@@ -0,0 +1,76 @@
+package org.oceandsl.tools.relable;
+
+import java.io.File;
+import java.nio.file.Files;
+
+import com.beust.jcommander.JCommander;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import kieker.common.configuration.Configuration;
+import kieker.common.exception.ConfigurationException;
+import kieker.tools.common.AbstractService;
+
+/**
+ * Architecture analysis main class.
+ *
+ * @author Reiner Jung
+ * @since 1.1
+ */
+public class RelabelSourceMain extends AbstractService<TeetimeConfiguration, Settings> {
+
+    /** logger for all tools. */
+    protected final Logger logger = LoggerFactory.getLogger(this.getClass().getCanonicalName()); // NOPMD
+
+    public static void main(final String[] args) {
+        final RelabelSourceMain main = new RelabelSourceMain();
+        try {
+            final int exitCode = main.run("relabel source information", "relabel", args, new Settings());
+            java.lang.System.exit(exitCode);
+        } catch (final IllegalArgumentException e) {
+            LoggerFactory.getLogger(RelabelSourceMain.class).error("Configuration error: {}", e.getLocalizedMessage());
+            java.lang.System.exit(1);
+        }
+    }
+
+    @Override
+    protected boolean checkParameters(final JCommander commander) throws ConfigurationException {
+        if (!Files.isDirectory(this.parameterConfiguration.getInputDirectory())) {
+            this.logger.error("Input path {} is not a directory", this.parameterConfiguration.getInputDirectory());
+            return false;
+        }
+
+        if (!Files.isDirectory(this.parameterConfiguration.getOutputDirectory())) {
+            this.logger.error("Output path {} is not directory", this.parameterConfiguration.getOutputDirectory());
+            return false;
+        }
+
+        if (this.parameterConfiguration.getReplacements().size() == 0) {
+            this.logger.error("Need to specify at least one replacement rule.");
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    protected TeetimeConfiguration createTeetimeConfiguration() throws ConfigurationException {
+        return new TeetimeConfiguration(this.parameterConfiguration);
+    }
+
+    @Override
+    protected File getConfigurationFile() {
+        return null;
+    }
+
+    @Override
+    protected boolean checkConfiguration(final Configuration configuration, final JCommander commander) {
+        return true;
+    }
+
+    @Override
+    protected void shutdownService() {
+    }
+
+}
diff --git a/tools/relabel/src/main/java/org/oceandsl/tools/relable/ReplaceSourceLabelStage.java b/tools/relabel/src/main/java/org/oceandsl/tools/relable/ReplaceSourceLabelStage.java
new file mode 100644
index 0000000000000000000000000000000000000000..74da5b26ed824be8277c3363c6ec9c4033eb5a5e
--- /dev/null
+++ b/tools/relabel/src/main/java/org/oceandsl/tools/relable/ReplaceSourceLabelStage.java
@@ -0,0 +1,71 @@
+/***************************************************************************
+ * Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
+package org.oceandsl.tools.relable;
+
+import java.util.List;
+import java.util.Map.Entry;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EObject;
+
+import kieker.analysis.stage.model.ModelRepository;
+import kieker.model.analysismodel.sources.SourceModel;
+import teetime.stage.basic.AbstractFilter;
+
+/**
+ * @author Reiner Jung
+ * @since 1.1
+ */
+public class ReplaceSourceLabelStage extends AbstractFilter<ModelRepository> {
+
+    private final List<Replacement> replacements;
+
+    public ReplaceSourceLabelStage(final List<Replacement> replacements) {
+        this.replacements = replacements;
+    }
+
+    @Override
+    protected void execute(final ModelRepository element) throws Exception {
+        final SourceModel sourceModel = element.getModel(SourceModel.class);
+        for (final Replacement replacement : this.replacements) {
+            this.processModel(sourceModel, replacement);
+        }
+        this.outputPort.send(element);
+    }
+
+    private void processModel(final SourceModel sourceModel, final Replacement replacement) {
+        for (final Entry<EObject, EList<String>> entry : sourceModel.getSources()) {
+            this.processReplacement(replacement, entry.getValue());
+        }
+    }
+
+    private void processReplacement(final Replacement replacement, final EList<String> labels) {
+        int matches = 0;
+        for (final String find : replacement.getSources()) {
+            if (labels.contains(find)) {
+                matches++;
+            }
+        }
+        if (matches == replacement.getSources().size()) {
+            for (final String find : replacement.getSources()) {
+                labels.remove(find);
+            }
+            if (!labels.contains(replacement.getTarget())) {
+                labels.add(replacement.getTarget());
+            }
+        }
+    }
+}
diff --git a/tools/relabel/src/main/java/org/oceandsl/tools/relable/Replacement.java b/tools/relabel/src/main/java/org/oceandsl/tools/relable/Replacement.java
new file mode 100644
index 0000000000000000000000000000000000000000..dbf3bce4b91af78549ffc002f8573ccd7e741deb
--- /dev/null
+++ b/tools/relabel/src/main/java/org/oceandsl/tools/relable/Replacement.java
@@ -0,0 +1,44 @@
+/***************************************************************************
+ * Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
+package org.oceandsl.tools.relable;
+
+import java.util.List;
+
+/**
+ * Description for one replacement rule.
+ *
+ * @author Reiner Jung
+ * @since 1.1
+ */
+public class Replacement {
+
+    private final List<String> sources;
+
+    private final String target;
+
+    public Replacement(final List<String> sources, final String target) {
+        this.sources = sources;
+        this.target = target;
+    }
+
+    public List<String> getSources() {
+        return this.sources;
+    }
+
+    public String getTarget() {
+        return this.target;
+    }
+}
diff --git a/tools/relabel/src/main/java/org/oceandsl/tools/relable/ReplacementConverter.java b/tools/relabel/src/main/java/org/oceandsl/tools/relable/ReplacementConverter.java
new file mode 100644
index 0000000000000000000000000000000000000000..093d09bbbdb129e382261d081eb4d36c037f9418
--- /dev/null
+++ b/tools/relabel/src/main/java/org/oceandsl/tools/relable/ReplacementConverter.java
@@ -0,0 +1,42 @@
+/***************************************************************************
+ * Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
+package org.oceandsl.tools.relable;
+
+import java.util.Arrays;
+import java.util.List;
+
+import com.beust.jcommander.IStringConverter;
+
+/**
+ *
+ * @author Reiner Jung
+ * @since 1.1
+ */
+public class ReplacementConverter implements IStringConverter<Replacement> {
+
+    @Override
+    public Replacement convert(final String value) {
+        final String[] rule = value.split(":");
+        if (rule.length == 2) {
+            final List<String> sources = Arrays.asList(rule[0].split(","));
+            return new Replacement(sources, rule[1]);
+        } else {
+            System.err.printf("Format of replacement rule is not supported: %s", value);
+            return null;
+        }
+    }
+
+}
diff --git a/tools/relabel/src/main/java/org/oceandsl/tools/relable/Settings.java b/tools/relabel/src/main/java/org/oceandsl/tools/relable/Settings.java
new file mode 100644
index 0000000000000000000000000000000000000000..3d2f32b5663d84b8db56b1021ef050acbf7622a7
--- /dev/null
+++ b/tools/relabel/src/main/java/org/oceandsl/tools/relable/Settings.java
@@ -0,0 +1,56 @@
+package org.oceandsl.tools.relable;
+
+/***************************************************************************
+ * Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
+
+import java.nio.file.Path;
+import java.util.List;
+
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.converters.PathConverter;
+
+/**
+ * All settings including command line parameters for the analysis.
+ *
+ * @author Reiner Jung
+ * @since 1.0
+ */
+public class Settings {
+
+    @Parameter(names = { "-i",
+            "--call-input" }, required = false, converter = PathConverter.class, description = "Directory for the input model")
+    private Path inputDirectory;
+
+    @Parameter(names = { "-o",
+            "--output" }, required = true, converter = PathConverter.class, description = "Directory for the modified model")
+    private Path outputDirectory;
+
+    @Parameter(names = { "-r",
+            "--replacements" }, required = true, variableArity = true, converter = ReplacementConverter.class, description = "Replacement for labels s1,s2:target")
+    private List<Replacement> replacements;
+
+    public Path getOutputDirectory() {
+        return this.outputDirectory;
+    }
+
+    public Path getInputDirectory() {
+        return this.inputDirectory;
+    }
+
+    public List<Replacement> getReplacements() {
+        return this.replacements;
+    }
+}
diff --git a/tools/relabel/src/main/java/org/oceandsl/tools/relable/TeetimeConfiguration.java b/tools/relabel/src/main/java/org/oceandsl/tools/relable/TeetimeConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..b4c7b07f30bb32acdca390f2b7f4c3c3717b15df
--- /dev/null
+++ b/tools/relabel/src/main/java/org/oceandsl/tools/relable/TeetimeConfiguration.java
@@ -0,0 +1,23 @@
+package org.oceandsl.tools.relable;
+
+import org.oceandsl.architecture.model.stages.ModelRepositoryProducerStage;
+
+import teetime.framework.Configuration;
+
+/**
+ * Pipe and Filter configuration relabling tool.
+ *
+ * @author Reiner Jung
+ * @since 1.1
+ */
+public class TeetimeConfiguration extends Configuration {
+
+    public TeetimeConfiguration(final Settings settings) {
+        final ModelRepositoryProducerStage readerStage = new ModelRepositoryProducerStage(settings.getInputDirectory());
+        final ReplaceSourceLabelStage replaceSourceLabelStage = new ReplaceSourceLabelStage(settings.getReplacements());
+        final ModelRepositoryWriterStage writerStage = new ModelRepositoryWriterStage(settings.getOutputDirectory());
+
+        this.connectPorts(readerStage.getOutputPort(), replaceSourceLabelStage.getInputPort());
+        this.connectPorts(replaceSourceLabelStage.getOutputPort(), writerStage.getInputPort());
+    }
+}
diff --git a/tools/relabel/src/main/java/org/oceandsl/tools/relable/package-info.java b/tools/relabel/src/main/java/org/oceandsl/tools/relable/package-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..45974ead480e1cd432698abe31c0239aa57df205
--- /dev/null
+++ b/tools/relabel/src/main/java/org/oceandsl/tools/relable/package-info.java
@@ -0,0 +1 @@
+package org.oceandsl.tools.relable;
\ No newline at end of file
diff --git a/tools/sar/src/main/java/org/oceandsl/tools/sar/Settings.java b/tools/sar/src/main/java/org/oceandsl/tools/sar/Settings.java
index b289121f52a6b5b3fd2a74e1357570e03db35eb7..cc13ad01d53a74071cdf70764e09dae9a79081d4 100644
--- a/tools/sar/src/main/java/org/oceandsl/tools/sar/Settings.java
+++ b/tools/sar/src/main/java/org/oceandsl/tools/sar/Settings.java
@@ -52,17 +52,18 @@ public class Settings {
     @Parameter(names = { "-f",
             "--function-names" }, required = false, variableArity = true, converter = PathConverter.class, description = "Function file map CSV file")
     private List<Path> functionNameFiles;
-    
-    @Parameter(names = { "-m", "--missing-functions" }, required=false, converter = PathConverter.class, description = "Output file for the list of function without an associated file")
+
+    @Parameter(names = { "-m",
+            "--missing-functions" }, required = false, converter = PathConverter.class, description = "Output file for the list of function without an associated file")
     private Path missingFunctionsFile;
-    
+
     @Parameter(names = { "-o",
             "--output" }, required = true, converter = PathConverter.class, description = "Output directory to store graphics and statistics")
     private Path outputDirectory;
 
     @Parameter(names = { "-M",
-            "--component-map" }, required = false, converter = PathConverter.class, description = "Component, file and function map file")
-    private Path componentMapFile;
+            "--component-map" }, required = false, variableArity = true, converter = PathConverter.class, description = "Component, file and function map file")
+    private List<Path> componentMapFiles;
 
     @Parameter(names = { "-l", "--source-label" }, required = true, description = "Set source label for the read data")
     private String sourceLabel;
@@ -78,6 +79,10 @@ public class Settings {
     @Parameter(names = { "-E", "--experiment-name" }, required = true, description = "Name of the experiment")
     private String experimentName;
 
+    @Parameter(names = { "-n",
+            "--missing-mappings" }, required = false, converter = PathConverter.class, description = "Output file for files without a mapping in the mapping file.")
+    private Path missingMappingFile;
+
     public Path getOperationCallInputFile() {
         return this.operationCallInputFile;
     }
@@ -130,15 +135,19 @@ public class Settings {
         return this.experimentName;
     }
 
-    public Path getComponentMapFile() {
-        return this.componentMapFile;
+    public List<Path> getComponentMapFiles() {
+        return this.componentMapFiles;
     }
 
     public Path getDataflowInputFile() {
         return this.dataflowInputFile;
     }
 
-	public Path getMissingFunctionsFile() {
-		return this.missingFunctionsFile;
-	}
+    public Path getMissingFunctionsFile() {
+        return this.missingFunctionsFile;
+    }
+
+    public Path getMissingMappingFile() {
+        return this.missingMappingFile;
+    }
 }
diff --git a/tools/sar/src/main/java/org/oceandsl/tools/sar/StaticArchitectureRecoveryMain.java b/tools/sar/src/main/java/org/oceandsl/tools/sar/StaticArchitectureRecoveryMain.java
index 400d19ab080aed773eae9170933760b86953e6fb..66617923f9cee82ae9d383f8e1dd6dc721d51309 100644
--- a/tools/sar/src/main/java/org/oceandsl/tools/sar/StaticArchitectureRecoveryMain.java
+++ b/tools/sar/src/main/java/org/oceandsl/tools/sar/StaticArchitectureRecoveryMain.java
@@ -85,7 +85,7 @@ public class StaticArchitectureRecoveryMain {
      */
     private void execute(final JCommander commander, final String label) throws ConfigurationException {
     	this.repository = ArchitectureModelManagementFactory.createModelRepository(
-                this.settings.getExperimentName(), this.settings.getComponentMapFile() != null);
+                this.settings.getExperimentName(), this.settings.getComponentMapFiles() != null);
     	
         if (this.settings.getOperationCallInputFile() != null)
         	this.executeConfiguration("call", label, this.createTeetimeCallConfiguration());
diff --git a/tools/sar/src/main/java/org/oceandsl/tools/sar/TeetimeCallConfiguration.java b/tools/sar/src/main/java/org/oceandsl/tools/sar/TeetimeCallConfiguration.java
index 7b07665329a28dfb824b95ce830cb7af78e447f1..7f7003364d907e7f9b05310a5d48d2c49f91d2ab 100644
--- a/tools/sar/src/main/java/org/oceandsl/tools/sar/TeetimeCallConfiguration.java
+++ b/tools/sar/src/main/java/org/oceandsl/tools/sar/TeetimeCallConfiguration.java
@@ -22,9 +22,9 @@ import java.nio.file.Paths;
 import org.oceandsl.analysis.CSVFunctionCallReaderStage;
 import org.oceandsl.analysis.CallerCallee;
 import org.oceandsl.architecture.model.data.table.ValueConversionErrorException;
-import org.oceandsl.architecture.model.stages.OperationCallFixPathStage;
 import org.oceandsl.architecture.model.stages.CSVMapperStage;
 import org.oceandsl.architecture.model.stages.CountUniqueCallsStage;
+import org.oceandsl.architecture.model.stages.OperationCallFixPathStage;
 import org.oceandsl.tools.sar.stages.FileBasedCleanupComponentSignatureStage;
 import org.oceandsl.tools.sar.stages.MapBasedCleanupComponentSignatureStage;
 import org.oceandsl.tools.sar.stages.OperationAndCall4StaticDataStage;
@@ -69,12 +69,14 @@ public class TeetimeCallConfiguration extends Configuration {
 
         readerPort = readCsvStage.getOutputPort();
 
-        if ((settings.getFunctionNameFiles() != null) && !settings.getFunctionNameFiles().isEmpty()) {
-            final OperationCallFixPathStage fixPathStage = new OperationCallFixPathStage(settings.getFunctionNameFiles(),
-                    settings.getNamesSplitSymbol());
+        if (settings.getFunctionNameFiles() != null && !settings.getFunctionNameFiles().isEmpty()) {
+            final OperationCallFixPathStage fixPathStage = new OperationCallFixPathStage(
+                    settings.getFunctionNameFiles(), settings.getNamesSplitSymbol());
             if (settings.getMissingFunctionsFile() != null) {
-            	final StringFileWriterSink missingFunctionsListSink = new StringFileWriterSink(settings.getMissingFunctionsFile());
-                this.connectPorts(fixPathStage.getMissingOperationOutputPort(), missingFunctionsListSink.getInputPort());
+                final StringFileWriterSink missingFunctionsListSink = new StringFileWriterSink(
+                        settings.getMissingFunctionsFile());
+                this.connectPorts(fixPathStage.getMissingOperationOutputPort(),
+                        missingFunctionsListSink.getInputPort());
             }
             this.connectPorts(readerPort, fixPathStage.getInputPort());
             readerPort = fixPathStage.getOutputPort();
@@ -83,10 +85,11 @@ public class TeetimeCallConfiguration extends Configuration {
         this.connectPorts(readerPort, mapperStage.getInputPort());
         readerPort = mapperStage.getOutputPort();
 
-        if (settings.getComponentMapFile() != null) {
+        if (settings.getComponentMapFiles() != null) {
             logger.info("Map based component definition");
             final MapBasedCleanupComponentSignatureStage cleanupComponentSignatureStage = new MapBasedCleanupComponentSignatureStage(
-                    settings.getComponentMapFile(), settings.getCaseInsensitive());
+                    settings.getComponentMapFiles(), settings.getMissingMappingFile(), settings.getCallSplitSymbol(),
+                    settings.getCaseInsensitive());
 
             this.connectPorts(readerPort, cleanupComponentSignatureStage.getInputPort());
             readerPort = cleanupComponentSignatureStage.getOutputPort();
@@ -110,7 +113,7 @@ public class TeetimeCallConfiguration extends Configuration {
                 }
                 final Path path = Paths.get(signature);
                 final String name = path.getName(path.getNameCount() - 1).toString();
-                final String rest = (path.getParent() != null)
+                final String rest = path.getParent() != null
                         ? settings.getExperimentName() + "." + path.getParent().toString()
                         : settings.getExperimentName();
                 componentType.setName(name);
diff --git a/tools/sar/src/main/java/org/oceandsl/tools/sar/TeetimeDataflowConfiguration.java b/tools/sar/src/main/java/org/oceandsl/tools/sar/TeetimeDataflowConfiguration.java
index 3fc524aeb5fc72975a032fedbcdd4e44d4e40851..f9599de0407b5eb907086e9c2cc906a96dfbc592 100644
--- a/tools/sar/src/main/java/org/oceandsl/tools/sar/TeetimeDataflowConfiguration.java
+++ b/tools/sar/src/main/java/org/oceandsl/tools/sar/TeetimeDataflowConfiguration.java
@@ -24,7 +24,8 @@ import org.oceandsl.tools.sar.stages.dataflow.CountUniqueDataflowCallsStage;
 import org.oceandsl.tools.sar.stages.dataflow.DataAccess;
 import org.oceandsl.tools.sar.stages.dataflow.DeploymentModelDataflowAssemblerStage;
 import org.oceandsl.tools.sar.stages.dataflow.ExecutionModelDataflowAssemblerStage;
-import org.oceandsl.tools.sar.stages.dataflow.FileBasedCleanupComponentInDataflowSignatureStage;
+import org.oceandsl.tools.sar.stages.dataflow.FileBasedCleanupInDataflowSignatureStage;
+import org.oceandsl.tools.sar.stages.dataflow.MapBasedCleanupInDataflowSignatureStage;
 import org.oceandsl.tools.sar.stages.dataflow.TypeModelDataflowAssemblerStage;
 import org.slf4j.Logger;
 
@@ -56,11 +57,17 @@ public class TeetimeDataflowConfiguration extends Configuration {
 
         readerDataflowPort = readDataflowStage.getOutputPort();
 
-        if (settings.getComponentMapFile() != null) {
+        if (settings.getComponentMapFiles() != null) {
             logger.info("Map based component definition");
+            final MapBasedCleanupInDataflowSignatureStage cleanupComponentDataflowSignatureStage = new MapBasedCleanupInDataflowSignatureStage(
+                    settings.getComponentMapFiles(), settings.getMissingMappingFile(), settings.getCallSplitSymbol(),
+                    settings.getCaseInsensitive());
+
+            this.connectPorts(readerDataflowPort, cleanupComponentDataflowSignatureStage.getInputPort());
+            readerDataflowPort = cleanupComponentDataflowSignatureStage.getOutputPort();
         } else {
             logger.info("File based component definition");
-            final FileBasedCleanupComponentInDataflowSignatureStage cleanupComponentDataflowSignatureStage = new FileBasedCleanupComponentInDataflowSignatureStage(
+            final FileBasedCleanupInDataflowSignatureStage cleanupComponentDataflowSignatureStage = new FileBasedCleanupInDataflowSignatureStage(
                     settings.getCaseInsensitive());
 
             this.connectPorts(readerDataflowPort, cleanupComponentDataflowSignatureStage.getInputPort());
diff --git a/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/MapBasedCleanupComponentSignatureStage.java b/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/MapBasedCleanupComponentSignatureStage.java
index 45cdb30b6bd4080bb6385af4fb4ea492862c190c..53c271703df0d0291bab43028bec515e7800d381 100644
--- a/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/MapBasedCleanupComponentSignatureStage.java
+++ b/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/MapBasedCleanupComponentSignatureStage.java
@@ -17,10 +17,12 @@ package org.oceandsl.tools.sar.stages;
 
 import java.io.BufferedReader;
 import java.io.IOException;
+import java.io.PrintWriter;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.oceandsl.architecture.model.data.table.ValueConversionErrorException;
@@ -32,26 +34,33 @@ import org.oceandsl.architecture.model.data.table.ValueConversionErrorException;
 public class MapBasedCleanupComponentSignatureStage extends AbstractCleanupComponentSignatureStage {
 
     private final Map<String, String> componentMap = new HashMap<>();
+    private final PrintWriter missingMappingWriter;
 
-    public MapBasedCleanupComponentSignatureStage(final Path componentMapFile, final boolean caseInsensitive)
-            throws IOException, ValueConversionErrorException {
+    public MapBasedCleanupComponentSignatureStage(final List<Path> componentMapFiles, final Path missingMappingFile,
+            final String separator, final boolean caseInsensitive) throws IOException, ValueConversionErrorException {
         super(caseInsensitive);
-        this.logger.info("Reading map file {}", componentMapFile.toString());
-        final BufferedReader reader = Files.newBufferedReader(componentMapFile);
-        String line;
-        while ((line = reader.readLine()) != null) {
-            final String[] values = line.split(",");
-            if (values.length == 3) {
-                // 0 = component name
-                // 1 = file name
-                // 2 = function name
-                this.componentMap.put(this.convertToLowerCase(values[1].trim()),
-                        this.convertToLowerCase(values[0].trim().toLowerCase()));
-            } else {
-                this.logger.error("Entry incomplete '{}'", line.trim());
+        if (missingMappingFile != null) {
+            this.missingMappingWriter = new PrintWriter(Files.newBufferedWriter(missingMappingFile));
+        } else {
+            this.missingMappingWriter = null;
+        }
+        for (final Path componentMapFile : componentMapFiles) {
+            this.logger.info("Reading map file {}", componentMapFile.toString());
+            final BufferedReader reader = Files.newBufferedReader(componentMapFile);
+            String line;
+            while ((line = reader.readLine()) != null) {
+                final String[] values = line.split(separator);
+                if (values.length == 2) {
+                    // 0 = component name
+                    // 1 = file name
+                    this.componentMap.put(this.convertToLowerCase(values[1].trim()),
+                            this.convertToLowerCase(values[0].trim().toLowerCase()));
+                } else {
+                    this.logger.error("Entry incomplete '{}'", line.trim());
+                }
             }
+            reader.close();
         }
-        reader.close();
     }
 
     private String convertToLowerCase(final String string) {
@@ -76,9 +85,20 @@ public class MapBasedCleanupComponentSignatureStage extends AbstractCleanupCompo
                 return result;
             } else {
                 this.logger.warn("File '{}' has no component mapping. Signature '{}'", filename, signature);
-                return "??" + signature.toLowerCase();
+                if (this.missingMappingWriter != null) {
+                    this.missingMappingWriter.println(filename + "; " + signature);
+                }
+                return "unknown";
             }
         }
     }
 
+    @Override
+    protected void onTerminating() {
+        if (this.missingMappingWriter != null) {
+            this.missingMappingWriter.close();
+        }
+        super.onTerminating();
+    }
+
 }
diff --git a/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/AssemblyModelDataflowAssemblerStage.java b/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/AssemblyModelDataflowAssemblerStage.java
index 86afc7d6a691b5002ae10c36445c87a02be54ace..654e85b137eb2a4c3ca3dfa5d06aad683846a509 100644
--- a/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/AssemblyModelDataflowAssemblerStage.java
+++ b/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/AssemblyModelDataflowAssemblerStage.java
@@ -89,14 +89,23 @@ public class AssemblyModelDataflowAssemblerStage extends AbstractDataflowAssembl
         final String name = assemblyStorage.getStorageType().getName();
         assemblyComponent.getAssemblyStorages().removeKey(name);
 
-        final AssemblyComponent newAssemblyComponent = AssemblyFactory.eINSTANCE.createAssemblyComponent();
-        newAssemblyComponent
-                .setComponentType(this.findComponentType(TypeModelDataflowAssemblerStage.GLOBAL_PACKAGE + "." + name));
-        newAssemblyComponent.setSignature(TypeModelDataflowAssemblerStage.GLOBAL_PACKAGE + "." + name);
-        newAssemblyComponent.getAssemblyStorages().put(name, assemblyStorage);
-
-        this.addObjectToSource(newAssemblyComponent);
-        this.assemblyModel.getAssemblyComponents().put(newAssemblyComponent.getSignature(), newAssemblyComponent);
+        this.findOrCreateAssemblyComponent().getAssemblyStorages().put(name, assemblyStorage);
+    }
+
+    private AssemblyComponent findOrCreateAssemblyComponent() {
+        final AssemblyComponent existingAssemblyComponent = this.assemblyModel.getAssemblyComponents()
+                .get(TypeModelDataflowAssemblerStage.GLOBAL_PACKAGE);
+        if (existingAssemblyComponent == null) {
+            final AssemblyComponent newAssemblyComponent = AssemblyFactory.eINSTANCE.createAssemblyComponent();
+            newAssemblyComponent
+                    .setComponentType(this.findComponentType(TypeModelDataflowAssemblerStage.GLOBAL_PACKAGE));
+            newAssemblyComponent.setSignature(TypeModelDataflowAssemblerStage.GLOBAL_PACKAGE);
+            this.addObjectToSource(newAssemblyComponent);
+            this.assemblyModel.getAssemblyComponents().put(newAssemblyComponent.getSignature(), newAssemblyComponent);
+            return newAssemblyComponent;
+        } else {
+            return existingAssemblyComponent;
+        }
     }
 
     private ComponentType findComponentType(final String componentSignature) {
diff --git a/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/DataAccess.java b/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/DataAccess.java
index 9106b59730274b68b85af75f8e843f7fe32087c1..a3c851c588106e1ba99399c4c327f4d33652fcdb 100644
--- a/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/DataAccess.java
+++ b/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/DataAccess.java
@@ -22,9 +22,9 @@ package org.oceandsl.tools.sar.stages.dataflow;
 public class DataAccess {
 
     private String module;
-    private final String operation;
+    private String operation;
     private final EDirection direction;
-    private final String sharedData;
+    private String sharedData;
 
     public DataAccess(final String module, final String operation, final EDirection direction,
             final String sharedData) {
@@ -38,10 +38,18 @@ public class DataAccess {
         return this.module;
     }
 
+    public void setModule(final String module) {
+        this.module = module;
+    }
+
     public String getOperation() {
         return this.operation;
     }
 
+    public void setOperation(final String operation) {
+        this.operation = operation;
+    }
+
     public EDirection getDirection() {
         return this.direction;
     }
@@ -50,8 +58,7 @@ public class DataAccess {
         return this.sharedData;
     }
 
-    public void setModule(final String module) {
-        this.module = module;
+    public void setSharedData(final String sharedData) {
+        this.sharedData = sharedData;
     }
-
 }
diff --git a/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/DeploymentModelDataflowAssemblerStage.java b/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/DeploymentModelDataflowAssemblerStage.java
index 5834669d613868d71ce96d7dde30119a0b24f984..f9f66ee9afb405edf7713355fb7a47c2d3adf74f 100644
--- a/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/DeploymentModelDataflowAssemblerStage.java
+++ b/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/DeploymentModelDataflowAssemblerStage.java
@@ -105,8 +105,6 @@ public class DeploymentModelDataflowAssemblerStage extends AbstractDataflowAssem
         } else {
             DeployedComponent deployedComponent = deployedContext.getComponents().get(element.getModule());
             if (deployedComponent == null) {
-                this.logger.warn("Cannot find deployed component for {}", element.getModule());
-
                 deployedComponent = DeploymentFactory.eINSTANCE.createDeployedComponent();
                 deployedComponent.setSignature(element.getModule());
                 deployedComponent.setAssemblyComponent(this.findAssemblyComponent(element.getModule()));
@@ -116,8 +114,6 @@ public class DeploymentModelDataflowAssemblerStage extends AbstractDataflowAssem
             DeployedOperation deployedOperation = deployedComponent.getContainedOperations()
                     .get(element.getOperation());
             if (deployedOperation == null) {
-                this.logger.warn("Operation {} cannot be found in model.", element.getOperation());
-
                 final AssemblyComponent assemblyComponent = this.assemblyModel.getAssemblyComponents()
                         .get(element.getModule());
                 final AssemblyOperation assemblyOperation = assemblyComponent.getAssemblyOperations()
@@ -136,15 +132,23 @@ public class DeploymentModelDataflowAssemblerStage extends AbstractDataflowAssem
         final String name = deployedStorage.getAssemblyStorage().getStorageType().getName();
         deployedComponent.getContainedStorages().removeKey(name);
 
-        final DeployedComponent newDeployedComponent = DeploymentFactory.eINSTANCE.createDeployedComponent();
-        newDeployedComponent.setAssemblyComponent(
-                this.findAssemblyComponent(TypeModelDataflowAssemblerStage.GLOBAL_PACKAGE + "." + name));
-        newDeployedComponent.setSignature(TypeModelDataflowAssemblerStage.GLOBAL_PACKAGE + "." + name);
-        newDeployedComponent.getContainedStorages().put(name, deployedStorage);
+        final DeploymentContext context = deployedComponent.getDeploymentContext();
+
+        final DeployedComponent existingComponent = context.getComponents()
+                .get(TypeModelDataflowAssemblerStage.GLOBAL_PACKAGE);
 
-        this.addObjectToSource(newDeployedComponent);
-        this.deploymentModel.getDeploymentContexts().get(0).getValue().getComponents()
-                .put(newDeployedComponent.getSignature(), newDeployedComponent);
+        if (existingComponent == null) {
+            final DeployedComponent newDeployedComponent = DeploymentFactory.eINSTANCE.createDeployedComponent();
+            newDeployedComponent
+                    .setAssemblyComponent(this.findAssemblyComponent(TypeModelDataflowAssemblerStage.GLOBAL_PACKAGE));
+            newDeployedComponent.setSignature(TypeModelDataflowAssemblerStage.GLOBAL_PACKAGE);
+            newDeployedComponent.getContainedStorages().put(name, deployedStorage);
+
+            this.addObjectToSource(newDeployedComponent);
+            context.getComponents().put(newDeployedComponent.getSignature(), newDeployedComponent);
+        } else {
+            existingComponent.getContainedStorages().put(name, deployedStorage);
+        }
     }
 
     private AssemblyComponent findAssemblyComponent(final String signature) {
diff --git a/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/FileBasedCleanupComponentInDataflowSignatureStage.java b/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/FileBasedCleanupInDataflowSignatureStage.java
similarity index 73%
rename from tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/FileBasedCleanupComponentInDataflowSignatureStage.java
rename to tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/FileBasedCleanupInDataflowSignatureStage.java
index 2f07bf7d2d897fb005123089a14c183561c86fdb..8e10eccc256742c9528e61da0e2d4188b054a779 100644
--- a/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/FileBasedCleanupComponentInDataflowSignatureStage.java
+++ b/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/FileBasedCleanupInDataflowSignatureStage.java
@@ -21,20 +21,25 @@ import java.nio.file.Paths;
 import teetime.stage.basic.AbstractTransformation;
 
 /**
- * @author Reiner Jung
+ * Cleanup names and make them lower case if requested.
  *
+ * @author Reiner Jung
+ * @since 1.1
  */
-public class FileBasedCleanupComponentInDataflowSignatureStage extends AbstractTransformation<DataAccess, DataAccess> {
+public class FileBasedCleanupInDataflowSignatureStage extends AbstractTransformation<DataAccess, DataAccess> {
 
     private final boolean caseInsensitive;
 
-    public FileBasedCleanupComponentInDataflowSignatureStage(final boolean caseInsensitive) {
+    public FileBasedCleanupInDataflowSignatureStage(final boolean caseInsensitive) {
         this.caseInsensitive = caseInsensitive;
     }
 
     @Override
     protected void execute(final DataAccess element) throws Exception {
-        element.setModule(this.convertToLowerCase(this.processComponentSignature(element.getModule())));
+        element.setModule(this.convertToLowerCase(this.processSignature(element.getModule())));
+        element.setOperation(this.convertToLowerCase(this.processSignature(element.getOperation())));
+        element.setSharedData(this.convertToLowerCase(this.processSignature(element.getSharedData())));
+
         this.outputPort.send(element);
     }
 
@@ -48,7 +53,7 @@ public class FileBasedCleanupComponentInDataflowSignatureStage extends AbstractT
         return this.caseInsensitive ? value.toLowerCase() : value;
     }
 
-    private String processComponentSignature(final String signature) {
+    private String processSignature(final String signature) {
         if ("<<no-file>>".equals(signature)) {
             return signature;
         } else {
diff --git a/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/MapBasedCleanupInDataflowSignatureStage.java b/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/MapBasedCleanupInDataflowSignatureStage.java
new file mode 100644
index 0000000000000000000000000000000000000000..1c5286a8f3b967f260c3cf69dca0fa6694bcdcbe
--- /dev/null
+++ b/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/MapBasedCleanupInDataflowSignatureStage.java
@@ -0,0 +1,109 @@
+/***************************************************************************
+ * Copyright (C) 2021 OceanDSL (https://oceandsl.uni-kiel.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
+package org.oceandsl.tools.sar.stages.dataflow;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import teetime.stage.basic.AbstractTransformation;
+
+/**
+ * Cleanup names and make them lower case if requested.
+ *
+ * @author Reiner Jung
+ * @since 1.1
+ */
+public class MapBasedCleanupInDataflowSignatureStage extends AbstractTransformation<DataAccess, DataAccess> {
+
+    private final boolean caseInsensitive;
+    private final Map<String, String> componentMap = new HashMap<>();
+
+    public MapBasedCleanupInDataflowSignatureStage(final List<Path> componentMapFiles, final Path missingMappingFile,
+            final String seperator, final boolean caseInsensitive) throws IOException {
+        this.caseInsensitive = caseInsensitive;
+        this.setupMap(componentMapFiles, seperator);
+    }
+
+    private void setupMap(final List<Path> componentMapFiles, final String separator) throws IOException {
+        for (final Path componentMapFile : componentMapFiles) {
+            this.logger.info("Reading map file {}", componentMapFile.toString());
+            final BufferedReader reader = Files.newBufferedReader(componentMapFile);
+            String line;
+            while ((line = reader.readLine()) != null) {
+                final String[] values = line.split(separator);
+                if (values.length == 2) {
+                    // 0 = component name
+                    // 1 = file name
+                    this.componentMap.put(this.convertToLowerCase(values[1].trim()),
+                            this.convertToLowerCase(values[0].trim().toLowerCase()));
+                } else {
+                    this.logger.error("Entry incomplete '{}'", line.trim());
+                }
+            }
+            reader.close();
+        }
+    }
+
+    @Override
+    protected void execute(final DataAccess element) throws Exception {
+        element.setModule(this.convertToLowerCase(this.processComponentSignature(element.getModule())));
+        element.setOperation(this.convertToLowerCase(this.processSignature(element.getOperation())));
+        element.setSharedData(this.convertToLowerCase(this.processSignature(element.getSharedData())));
+
+        this.outputPort.send(element);
+    }
+
+    private String convertToLowerCase(final String string) {
+        String value;
+        if (string.endsWith("_")) {
+            value = string.substring(0, string.length() - 1);
+        } else {
+            value = string;
+        }
+        return this.caseInsensitive ? value.toLowerCase() : value;
+    }
+
+    private String processSignature(final String signature) {
+        if ("<<no-file>>".equals(signature)) {
+            return signature;
+        } else {
+            final Path path = Paths.get(signature);
+            return this.convertToLowerCase(path.getName(path.getNameCount() - 1).toString());
+        }
+    }
+
+    private String processComponentSignature(final String signature) {
+        if ("<<no-file>>".equals(signature)) {
+            return signature;
+        } else {
+            final Path path = Paths.get(signature);
+            final String filename = this.convertToLowerCase(path.getName(path.getNameCount() - 1).toString());
+            final String result = this.componentMap.get(filename);
+            if (result != null) {
+                return result;
+            } else {
+                this.logger.warn("File '{}' has no component mapping. Signature '{}'", filename, signature);
+                return "unknown";
+            }
+        }
+    }
+}
diff --git a/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/TypeModelDataflowAssemblerStage.java b/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/TypeModelDataflowAssemblerStage.java
index daab258ca02ed7ad0386f1c23f53466f735f0937..24a732cfc41ad5b81170d5f06f703053ab445cef 100644
--- a/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/TypeModelDataflowAssemblerStage.java
+++ b/tools/sar/src/main/java/org/oceandsl/tools/sar/stages/dataflow/TypeModelDataflowAssemblerStage.java
@@ -89,14 +89,25 @@ public class TypeModelDataflowAssemblerStage extends AbstractDataflowAssemblerSt
             final ComponentType componentType) {
         componentType.getProvidedStorages().removeKey(storageType.getName());
 
-        final ComponentType newComponentType = TypeFactory.eINSTANCE.createComponentType();
-        newComponentType.setName(storageType.getName());
-        newComponentType.setPackage(TypeModelDataflowAssemblerStage.GLOBAL_PACKAGE);
-        newComponentType.setSignature(TypeModelDataflowAssemblerStage.GLOBAL_PACKAGE + "." + storageType.getName());
-        newComponentType.getProvidedStorages().put(storageType.getName(), storageType);
-
-        this.addObjectToSource(newComponentType);
-        this.typeModel.getComponentTypes().put(newComponentType.getSignature(), newComponentType);
+        this.findOrCreateGlobalComponentType().getProvidedStorages().put(storageType.getName(), storageType);
+    }
+
+    private ComponentType findOrCreateGlobalComponentType() {
+        final ComponentType componentType = this.typeModel.getComponentTypes()
+                .get(TypeModelDataflowAssemblerStage.GLOBAL_PACKAGE);
+        if (componentType != null) {
+            return componentType;
+        } else {
+            final ComponentType newComponentType = TypeFactory.eINSTANCE.createComponentType();
+            newComponentType.setName(TypeModelDataflowAssemblerStage.GLOBAL_PACKAGE);
+            newComponentType.setPackage(TypeModelDataflowAssemblerStage.GLOBAL_PACKAGE);
+            newComponentType.setSignature(TypeModelDataflowAssemblerStage.GLOBAL_PACKAGE);
+
+            this.typeModel.getComponentTypes().put(newComponentType.getSignature(), newComponentType);
+            this.addObjectToSource(newComponentType);
+
+            return newComponentType;
+        }
     }
 
     private OperationType findOperation(final DataAccess element) {
@@ -111,7 +122,7 @@ public class TypeModelDataflowAssemblerStage extends AbstractDataflowAssemblerSt
             this.typeModel.getComponentTypes().put(element.getModule(), componentType);
             final OperationType operationType = this.createOperation(element.getOperation());
             componentType.getProvidedOperations().put(element.getOperation(), operationType);
-            
+
             return operationType;
         } else {
             for (final OperationType operation : componentType.getProvidedOperations().values()) {