diff --git a/pom.xml b/pom.xml
index a6b8b4d9abf66633703fbfacc8f569ed4dbb851e..8000360b5ec46ea5a4dc05d8bd54275a0ffdb048 100644
--- a/pom.xml
+++ b/pom.xml
@@ -93,12 +93,12 @@
 		<dependency>
 			<groupId>org.slf4j</groupId>
 			<artifactId>slf4j-api</artifactId>
-			<version>1.7.16</version>
+			<version>1.7.18</version>
 		</dependency>
 		<dependency>
 			<groupId>ch.qos.logback</groupId>
 			<artifactId>logback-classic</artifactId>
-			<version>1.1.5</version>
+			<version>1.1.6</version>
 			<scope>runtime</scope>
 		</dependency>
 		<dependency>
@@ -175,7 +175,7 @@
 			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
 				<artifactId>maven-source-plugin</artifactId>
-				<version>2.4</version>
+				<version>3.0.0</version>
 				<executions>
 					<execution>
 						<id>attach-sources</id>
diff --git a/src/main/java/kieker/analysis/TraceAnalysis.java b/src/main/java/kieker/analysis/TraceAnalysis.java
index c0f18e61bcda17afe6c28af9c7ae904813f4d48e..e92079d258318ad18bc49854e913e678b53e10c3 100644
--- a/src/main/java/kieker/analysis/TraceAnalysis.java
+++ b/src/main/java/kieker/analysis/TraceAnalysis.java
@@ -5,11 +5,6 @@ package kieker.analysis;
 
 import java.io.File;
 
-import com.tinkerpop.blueprints.Edge;
-import com.tinkerpop.blueprints.Graph;
-import com.tinkerpop.blueprints.Vertex;
-import com.tinkerpop.blueprints.impls.tg.TinkerGraph;
-
 import teetime.framework.Execution;
 
 /**
@@ -26,19 +21,6 @@ public final class TraceAnalysis {
 		final Execution<TraceAnalysisConfiguration> analysis = new Execution<>(traceAnalysisConfiguration);
 		analysis.executeBlocking();
 
-		/*
-		 *
-		 *
-		 *
-		 * TODO
-		 */
-
-		Graph graph = new TinkerGraph();
-
-		Vertex vertex = graph.addVertex(101);
-
-		Edge edge = vertex.addEdge("Label", vertex);
-
 	}
 
 }
diff --git a/src/main/java/kieker/analysis/TraceAnalysisConfiguration.java b/src/main/java/kieker/analysis/TraceAnalysisConfiguration.java
index e78b6a3561d27758714121ac2a4052b332ef6d1d..127fe1a372cf3fd985f89be83251b095f4c48202 100644
--- a/src/main/java/kieker/analysis/TraceAnalysisConfiguration.java
+++ b/src/main/java/kieker/analysis/TraceAnalysisConfiguration.java
@@ -7,10 +7,6 @@ import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
 
-import com.tinkerpop.blueprints.Graph;
-
-import kieker.analysis.dev.DependencyCreatorStage;
-import kieker.analysis.dev.DependencyStatisticsDecoratorStage;
 import kieker.analysis.domain.AggregatedOperationCall;
 import kieker.analysis.domain.AggregatedTrace;
 import kieker.analysis.domain.OperationCall;
@@ -21,11 +17,11 @@ import kieker.analysis.stage.tracediagnosis.OperationCallHandlerComposite;
 import kieker.analysis.stage.tracediagnosis.ReadingComposite;
 import kieker.analysis.stage.tracediagnosis.TraceAggregationComposite;
 import kieker.analysis.stage.tracediagnosis.TraceReconstructionComposite;
-import kieker.analysis.trace.graphoutput.DotGraphWriter;
-import kieker.analysis.trace.graphoutput.GraphMLWriter;
+import kieker.analysis.trace.graphoutput.DotTraceGraphFileWriterStage;
 import kieker.analysis.trace.traversal.AggrTraceTraverserStage;
 import kieker.analysis.trace.traversal.TraceTraverserStage;
-import kieker.analysis.util.graph.NamedGraph;
+import kieker.analysis.util.graph.Graph;
+import kieker.analysis.util.graph.export.graphml.GraphMLFileWriterStage;
 import kieker.common.record.IMonitoringRecord;
 import kieker.common.record.misc.KiekerMetadataRecord;
 
@@ -78,46 +74,38 @@ public class TraceAnalysisConfiguration extends Configuration {
 		String graphFilesOutputDir = "example/event monitoring log/output"; // TODO Temp hard coded
 
 		TraceTraverserStage traceTraverserStage = new TraceTraverserStage();
-		final Distributor<NamedGraph<Graph>> graphDistributor = new Distributor<>(new CopyByReferenceStrategy());
-		GraphMLWriter graphMLWriter = new GraphMLWriter(graphFilesOutputDir);
-		DotGraphWriter dotGraphWriter = new DotGraphWriter(graphFilesOutputDir);
+		final Distributor<Graph> graphDistributor = new Distributor<>(new CopyByReferenceStrategy());
+		GraphMLFileWriterStage graphMLFileWriterComposite = new GraphMLFileWriterStage(graphFilesOutputDir);
+		DotTraceGraphFileWriterStage dotTraceGraphFileWriterStage = new DotTraceGraphFileWriterStage(graphFilesOutputDir);
 
 		super.connectPorts(distributor.getNewOutputPort(), traceTraverserStage.getInputPort());
 		super.connectPorts(traceTraverserStage.getOutputPort(), graphDistributor.getInputPort());
-		super.connectPorts(graphDistributor.getNewOutputPort(), graphMLWriter.getInputPort());
-		super.connectPorts(graphDistributor.getNewOutputPort(), dotGraphWriter.getInputPort());
+		super.connectPorts(graphDistributor.getNewOutputPort(), graphMLFileWriterComposite.getInputPort());
+		super.connectPorts(graphDistributor.getNewOutputPort(), dotTraceGraphFileWriterStage.getInputPort());
 
 		final Distributor<AggregatedTrace> aggregatedTraceDistributor = new Distributor<>(new CopyByReferenceStrategy());
 		AggrTraceTraverserStage aggrTraceTraverser = new AggrTraceTraverserStage();
-		final Distributor<NamedGraph<Graph>> graphDistributor2 = new Distributor<>(new CopyByReferenceStrategy());
-		GraphMLWriter graphMLWriter2 = new GraphMLWriter(graphFilesOutputDir);
-		DotGraphWriter dotGraphWriter2 = new DotGraphWriter(graphFilesOutputDir);
+		final Distributor<Graph> graphDistributor2 = new Distributor<>(new CopyByReferenceStrategy());
+		GraphMLFileWriterStage graphMLFileWriterComposite2 = new GraphMLFileWriterStage(graphFilesOutputDir);
+		DotTraceGraphFileWriterStage dotTraceGraphFileWriterStage2 = new DotTraceGraphFileWriterStage(graphFilesOutputDir);
 
 		super.connectPorts(aggregation.getOutputPort(), aggregatedTraceDistributor.getInputPort());
 
 		super.connectPorts(aggregatedTraceDistributor.getNewOutputPort(), aggrTraceTraverser.getInputPort());
 		super.connectPorts(aggrTraceTraverser.getOutputPort(), graphDistributor2.getInputPort());
-		super.connectPorts(graphDistributor2.getNewOutputPort(), graphMLWriter2.getInputPort());
-		super.connectPorts(graphDistributor2.getNewOutputPort(), dotGraphWriter2.getInputPort());
+		super.connectPorts(graphDistributor2.getNewOutputPort(), graphMLFileWriterComposite2.getInputPort());
+		super.connectPorts(graphDistributor2.getNewOutputPort(), dotTraceGraphFileWriterStage2.getInputPort());
 
-		DependencyCreatorStage dependencyCreatorStage = new DependencyCreatorStage();
-		DependencyStatisticsDecoratorStage dependencyStatisticsDecoratorStage = new DependencyStatisticsDecoratorStage();
-		super.connectPorts(aggregatedTraceDistributor.getNewOutputPort(), dependencyCreatorStage.getInputPort());
-		super.connectPorts(dependencyCreatorStage.getOutputPort(), dependencyStatisticsDecoratorStage.getInputPort());
+		// DependencyCreatorStage dependencyCreatorStage = new DependencyCreatorStage();
+		// DependencyStatisticsDecoratorStage dependencyStatisticsDecoratorStage = new DependencyStatisticsDecoratorStage();
+		// super.connectPorts(aggregatedTraceDistributor.getNewOutputPort(), dependencyCreatorStage.getInputPort());
+		// super.connectPorts(dependencyCreatorStage.getOutputPort(), dependencyStatisticsDecoratorStage.getInputPort());
 
 		/*
 		 *
 		 *
 		 */
 
-		// TODO Temp Some examples for nested graphs
-		//
-		// final NestedGraphFactory nestedGraphFactory = new NestedGraphFactory();
-		// final ObjectProducer<NestedGraph<Graph>> nestedGraphProducerStage = new ObjectProducer<>(1, nestedGraphFactory);
-		// final NestedGraphPrinterStage nestedGraphPrinterStage = new NestedGraphPrinterStage();
-		//
-		// super.connectPorts(nestedGraphProducerStage.getOutputPort(), nestedGraphPrinterStage.getInputPort());
-
 	}
 
 	public long getBeginTimestamp() {
diff --git a/src/main/java/kieker/analysis/dev/GraphTester.java b/src/main/java/kieker/analysis/dev/GraphTester.java
new file mode 100644
index 0000000000000000000000000000000000000000..7de747dd3ce3c2d5a4e69f310998b731aae50382
--- /dev/null
+++ b/src/main/java/kieker/analysis/dev/GraphTester.java
@@ -0,0 +1,145 @@
+package kieker.analysis.dev;
+
+import java.io.OutputStreamWriter;
+import java.util.ArrayList;
+
+import kieker.analysis.util.graph.Edge;
+import kieker.analysis.util.graph.Graph;
+import kieker.analysis.util.graph.Vertex;
+import kieker.analysis.util.graph.export.dot.DotExporter;
+import kieker.analysis.util.graph.impl.GraphImpl;
+
+public class GraphTester {
+
+	public static void main(final String[] args) {
+
+		Graph graph = new GraphImpl();
+
+		Vertex node1 = graph.addVertex("n1");
+
+		Vertex node2 = graph.addVertex("n2");
+
+		Vertex node3 = graph.addVertex("n3");
+
+		Vertex node4 = graph.addVertex("n4");
+
+		Edge edge12 = node1.addEdge(node2);
+		Edge edge11 = node1.addEdge(node1);
+		edge11.setProperty("label", "label-LABELNAME");
+
+		Edge edge23 = node2.addEdge("e23", node3);
+
+		graph.addEdge("e13", node1, node3);
+
+		Vertex node1snd = graph.getVertex("n1");
+
+		assert node1 == node1snd;
+
+		System.out.println("Master graph");
+
+		for (Vertex vertex : graph.getVertices()) {
+			System.out.println(vertex.getId());
+		}
+
+		for (Edge edge : graph.getEdges()) {
+			System.out.println(edge.getId());
+		}
+
+		// BlueprintsExporter blueprintsExporter = new BlueprintsExporter(graph);
+		// System.out.println(blueprintsExporter.exportGraph());
+
+		// node1snd.remove();
+
+		for (Vertex vertex : graph.getVertices()) {
+			System.out.println(vertex.getId());
+		}
+
+		node1.addChildGraph();
+
+		Vertex node1sub1 = node1.getChildGraph().addVertex("n1::s1");
+		Vertex node1sub2 = node1.getChildGraph().addVertex("n1::s2");
+		Vertex node1sub3 = node1.getChildGraph().addVertex("n1::s3");
+		node1sub3.addEdge("wormhole1", node4);
+		node4.addEdge("wormhole2", node1sub3);
+
+		node1sub3.addChildGraph();
+		Vertex node1sub3sub1 = node1sub3.getChildGraph().addVertex("n1::s3::s1");
+		Vertex node1sub3sub2 = node1sub3.getChildGraph().addVertex("n1::s3::s2");
+		Vertex node1sub3sub3 = node1sub3.getChildGraph().addVertex("n1::s3::s3");
+		node1sub3sub1.addEdge("wormhole3", node4);
+		node4.addEdge("wormhole4", node1sub3sub1);
+		node1sub3sub2.addEdge(node1sub3sub3);
+
+		node1sub2.addChildGraph();
+		Vertex node1sub2sub1 = node1sub2.getChildGraph().addVertex("n1::s2::s1");
+		node1sub2sub1.addEdge("hyperwormhole", node1sub3sub1);
+
+		if (node1.hasChildGraph()) {
+			System.out.println("Node 1 has Child graph");
+		} else {
+			System.out.println("Node 1 does not have a child graph");
+		}
+
+		System.out.println("Node 1's child graph");
+
+		for (Vertex vertex : node1.getChildGraph().getVertices()) {
+			System.out.println(vertex.getId());
+		}
+
+		for (Edge edge : node1.getChildGraph().getEdges()) {
+			System.out.println(edge.getId());
+		}
+
+		System.out.println("Master graph");
+
+		for (Vertex vertex : graph.getVertices()) {
+			System.out.println(vertex.getId());
+		}
+
+		for (Edge edge : graph.getEdges()) {
+			System.out.println(edge.getId());
+		}
+
+		// Add some labels for nodes
+		for (Vertex vertex : graph.getVertices()) {
+			vertex.setProperty("label", "-[label]-" + vertex.getId().toString());
+		}
+
+		// Add some stuff for nodes
+		for (Vertex vertex : graph.getVertices()) {
+			vertex.setProperty("abcprop", 2016);
+			vertex.setProperty("xyzprop", new ArrayList<Boolean>());
+		}
+
+		DotExporter dotWriter = new DotExporter(graph, new OutputStreamWriter(System.out));
+		dotWriter.transform();
+
+		DotExporter dotExporter = new DotExporter(graph, new OutputStreamWriter(System.out));
+		dotExporter.transform();
+
+		// Could be useful for testing
+		//
+		// System.out.println("DotWriter Test");
+		//
+		// DotWriter dotWriter = new DotWriter(new PrintWriter(System.out));
+		// try {
+		// dotWriter.start("G");
+		// dotWriter.addGraphAttribute("rotate", "90");
+		// Map<String, String> defaultNodeAttributes = new HashMap<>();
+		// defaultNodeAttributes.put("style", "filled");
+		// dotWriter.addDefaultNodeAttributes(defaultNodeAttributes);
+		// Map<String, String> nodeAttributes = new HashMap<>();
+		// nodeAttributes.put("label", "LABEL Title");
+		// dotWriter.addNode("102", nodeAttributes);
+		// dotWriter.addNode("#id", nodeAttributes);
+		// dotWriter.addEdge("102", "#id", new HashMap<>());
+		// dotWriter.finish();
+		//
+		// } catch (IOException e) {
+		// // TODO Auto-generated catch block
+		// e.printStackTrace();
+		// }
+
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/dev/nestedgraph/NestedGraph.java b/src/main/java/kieker/analysis/dev/nestedgraph/NestedGraph.java
deleted file mode 100644
index e6e59ba294b45edb81cc874f31bf5b274252a57b..0000000000000000000000000000000000000000
--- a/src/main/java/kieker/analysis/dev/nestedgraph/NestedGraph.java
+++ /dev/null
@@ -1,172 +0,0 @@
-package kieker.analysis.dev.nestedgraph;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import com.tinkerpop.blueprints.Edge;
-import com.tinkerpop.blueprints.Features;
-import com.tinkerpop.blueprints.Graph;
-import com.tinkerpop.blueprints.GraphQuery;
-import com.tinkerpop.blueprints.Vertex;
-import com.tinkerpop.blueprints.util.StringFactory;
-import com.tinkerpop.blueprints.util.wrappers.WrapperGraph;
-import com.tinkerpop.blueprints.util.wrappers.partition.PartitionGraph;
-
-public class NestedGraph<T extends Graph> implements Graph, WrapperGraph<T> {
-
-	protected PartitionGraph<T> baseGraph;
-
-	private final Features features;
-
-	private static final String PARTITION_KEY = "__nested-graph-partition";
-
-	private static final String DEFAULT_PARTITION = "";
-
-	private final Set<NestedGraphPartition> partitions = new HashSet<>();
-
-	public NestedGraph(final T baseGraph) {
-		this.baseGraph = new PartitionGraph<>(baseGraph, PARTITION_KEY, DEFAULT_PARTITION);
-		this.features = this.baseGraph.getFeatures().copyFeatures();
-		this.features.isWrapper = true;
-	}
-
-	public void addPartition(final NestedGraphPartition partition) {
-		partitions.add(partition);
-	}
-
-	public Iterable<NestedGraphPartition> getPartitions() {
-		return partitions;
-	}
-
-	public Iterable<Vertex> getVerticesForPartition(final NestedGraphPartition partition) {
-
-		baseGraph.removeReadPartition(DEFAULT_PARTITION);
-		baseGraph.addReadPartition(partition.getName());
-
-		Set<Vertex> vertices = new HashSet<Vertex>();
-		for (Vertex vertex : baseGraph.getVertices()) {
-			vertices.add(vertex);
-		}
-
-		baseGraph.removeReadPartition(partition.getName());
-		baseGraph.addReadPartition(DEFAULT_PARTITION);
-
-		return vertices;
-	}
-
-	public Iterable<Edge> getEdgesForPartition(final NestedGraphPartition partition) {
-
-		baseGraph.removeReadPartition(DEFAULT_PARTITION);
-		baseGraph.addReadPartition(partition.getName());
-
-		Set<Edge> edges = new HashSet<Edge>();
-		for (Edge edge : baseGraph.getEdges()) {
-			edges.add(edge);
-		}
-
-		baseGraph.removeReadPartition(partition.getName());
-		baseGraph.addReadPartition(DEFAULT_PARTITION);
-
-		return edges;
-	}
-
-	public Vertex addVertexToPartition(final Object id, final NestedGraphPartition partition) {
-
-		baseGraph.setWritePartition(partition.getName());
-
-		Vertex vertex = baseGraph.addVertex(id);
-
-		baseGraph.setWritePartition(DEFAULT_PARTITION);
-
-		return vertex;
-
-	}
-
-	public Edge addEdgeToPartition(final Object id, final Vertex outVertex, final Vertex inVertex, final String label, final NestedGraphPartition partition) {
-
-		baseGraph.setWritePartition(partition.getName());
-
-		Edge edge = baseGraph.addEdge(id, outVertex, inVertex, label);
-
-		baseGraph.setWritePartition(DEFAULT_PARTITION);
-
-		return edge;
-
-	}
-
-	@Override
-	public Vertex addVertex(final Object id) {
-		return baseGraph.addVertex(id);
-	}
-
-	@Override
-	public Vertex getVertex(final Object id) {
-		return baseGraph.getVertex(id);
-	}
-
-	@Override
-	public Iterable<Vertex> getVertices() {
-		return this.baseGraph.getVertices();
-	}
-
-	@Override
-	public Iterable<Vertex> getVertices(final String key, final Object value) {
-		return this.baseGraph.getVertices(key, value);
-	}
-
-	@Override
-	public Edge addEdge(final Object id, final Vertex outVertex, final Vertex inVertex, final String label) {
-		return baseGraph.addEdge(id, outVertex, inVertex, label);
-	}
-
-	@Override
-	public Edge getEdge(final Object id) {
-		return baseGraph.getEdge(id);
-	}
-
-	@Override
-	public Iterable<Edge> getEdges() {
-		return baseGraph.getEdges();
-	}
-
-	@Override
-	public Iterable<Edge> getEdges(final String key, final Object value) {
-		return this.baseGraph.getEdges(key, value);
-	}
-
-	@Override
-	public void removeEdge(final Edge edge) {
-		baseGraph.removeEdge(edge);
-	}
-
-	@Override
-	public void removeVertex(final Vertex vertex) {
-		baseGraph.removeVertex(vertex);
-	}
-
-	@Override
-	public T getBaseGraph() {
-		return baseGraph.getBaseGraph();
-	}
-
-	@Override
-	public GraphQuery query() {
-		return this.baseGraph.query();
-	}
-
-	@Override
-	public String toString() {
-		return StringFactory.graphString(this, this.baseGraph.toString());
-	}
-
-	@Override
-	public Features getFeatures() {
-		return this.features;
-	}
-
-	@Override
-	public void shutdown() {
-		this.baseGraph.shutdown();
-	}
-
-}
diff --git a/src/main/java/kieker/analysis/dev/nestedgraph/NestedGraphPartition.java b/src/main/java/kieker/analysis/dev/nestedgraph/NestedGraphPartition.java
deleted file mode 100644
index ce092e3af60e04326ba9aceaaf8a2d5f9548c4ee..0000000000000000000000000000000000000000
--- a/src/main/java/kieker/analysis/dev/nestedgraph/NestedGraphPartition.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package kieker.analysis.dev.nestedgraph;
-
-import java.util.HashSet;
-import java.util.Set;
-
-public class NestedGraphPartition {
-
-	private String name;
-
-	private String label;
-
-	private final Set<NestedGraphPartition> subPartitions = new HashSet<>();
-
-	public NestedGraphPartition(final String name) {
-		this(name, null);
-	}
-
-	public NestedGraphPartition(final String name, final String label) {
-		this.name = name;
-		this.label = label;
-	}
-
-	public String getName() {
-		return name;
-	}
-
-	public void setName(final String name) {
-		this.name = name;
-	}
-
-	public String getLabel() {
-		return label;
-	}
-
-	public void setLabel(final String label) {
-		this.label = label;
-	}
-
-	public Iterable<NestedGraphPartition> getSubPartitions() {
-		return subPartitions;
-	}
-
-	public void addSubPartition(final NestedGraphPartition subPartition) {
-		subPartitions.add(subPartition);
-	}
-
-}
diff --git a/src/main/java/kieker/analysis/dev/nestedgraph/SubGraph.java b/src/main/java/kieker/analysis/dev/nestedgraph/SubGraph.java
deleted file mode 100644
index 17a90c5f4be9cdb00460355ccaff469d69eef57e..0000000000000000000000000000000000000000
--- a/src/main/java/kieker/analysis/dev/nestedgraph/SubGraph.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package kieker.analysis.dev.nestedgraph;
-
-import com.tinkerpop.blueprints.Edge;
-import com.tinkerpop.blueprints.Features;
-import com.tinkerpop.blueprints.Graph;
-import com.tinkerpop.blueprints.GraphQuery;
-import com.tinkerpop.blueprints.Vertex;
-
-//TODO implements
-public class SubGraph implements Graph {
-
-	private final NestedGraph<Graph> mainGraph; // TODO has to be nestable Graph
-
-	public SubGraph(final NestedGraph<Graph> mainGraph) {
-		this.mainGraph = mainGraph;
-
-		// TODO subGraph beim mainGraph anmelden
-	}
-
-	public NestedGraph<Graph> getMainGraph() {
-		return mainGraph;
-	}
-
-	@Override
-	public Features getFeatures() {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public Vertex addVertex(final Object id) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public Vertex getVertex(final Object id) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public void removeVertex(final Vertex vertex) {
-		// TODO Auto-generated method stub
-
-	}
-
-	@Override
-	public Iterable<Vertex> getVertices() {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public Iterable<Vertex> getVertices(final String key, final Object value) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public Edge addEdge(final Object id, final Vertex outVertex, final Vertex inVertex, final String label) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public Edge getEdge(final Object id) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public void removeEdge(final Edge edge) {
-		// TODO Auto-generated method stub
-
-	}
-
-	@Override
-	public Iterable<Edge> getEdges() {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public Iterable<Edge> getEdges(final String key, final Object value) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public GraphQuery query() {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public void shutdown() {
-		// TODO Auto-generated method stub
-
-	}
-
-}
diff --git a/src/main/java/kieker/analysis/dev/nestedgraphstages/NestedGraphFactory.java b/src/main/java/kieker/analysis/dev/nestedgraphstages/NestedGraphFactory.java
deleted file mode 100644
index 1bb72a71bd330fcc41c53ef90242d96fa1e6a307..0000000000000000000000000000000000000000
--- a/src/main/java/kieker/analysis/dev/nestedgraphstages/NestedGraphFactory.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package kieker.analysis.dev.nestedgraphstages;
-
-import com.tinkerpop.blueprints.Graph;
-import com.tinkerpop.blueprints.Vertex;
-import com.tinkerpop.blueprints.impls.tg.TinkerGraph;
-
-import kieker.analysis.dev.nestedgraph.NestedGraph;
-import kieker.analysis.dev.nestedgraph.NestedGraphPartition;
-
-import teetime.util.ConstructorClosure;
-
-public class NestedGraphFactory implements ConstructorClosure<NestedGraph<Graph>> {
-
-	@Override
-	public NestedGraph<Graph> create() {
-
-		NestedGraph<Graph> graph = new NestedGraph<Graph>(new TinkerGraph());
-
-		Vertex entry = graph.addVertex("Entry");
-
-		NestedGraphPartition partitionBookstore = new NestedGraphPartition("Bookstore");
-		graph.addPartition(partitionBookstore);
-		Vertex searchBook = graph.addVertexToPartition("searchBook()", partitionBookstore);
-
-		NestedGraphPartition partitionCRM = new NestedGraphPartition("CRM");
-		graph.addPartition(partitionCRM);
-		Vertex getOffers = graph.addVertexToPartition("getOffers()", partitionCRM);
-		Vertex customMethod = graph.addVertexToPartition("customMethod()", partitionCRM);
-
-		NestedGraphPartition partitionCatalog = new NestedGraphPartition("Catalog");
-		graph.addPartition(partitionCatalog);
-		Vertex getBook = graph.addVertexToPartition("getBook()", partitionCatalog);
-
-		graph.addEdge(null, entry, searchBook, "100");
-		graph.addEdge(null, searchBook, getBook, "100");
-		graph.addEdge(null, searchBook, getOffers, "100");
-		graph.addEdge(null, getOffers, getBook, "96");
-		graph.addEdge(null, getOffers, customMethod, "0");
-
-		return graph;
-	}
-
-}
diff --git a/src/main/java/kieker/analysis/dev/nestedgraphstages/NestedGraphPrinterStage.java b/src/main/java/kieker/analysis/dev/nestedgraphstages/NestedGraphPrinterStage.java
deleted file mode 100644
index c5f2f8a32d0ec89ae6e1450e8d36fae2ecb7c421..0000000000000000000000000000000000000000
--- a/src/main/java/kieker/analysis/dev/nestedgraphstages/NestedGraphPrinterStage.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package kieker.analysis.dev.nestedgraphstages;
-
-import com.tinkerpop.blueprints.Edge;
-import com.tinkerpop.blueprints.Graph;
-import com.tinkerpop.blueprints.Vertex;
-
-import kieker.analysis.dev.nestedgraph.NestedGraph;
-import kieker.analysis.dev.nestedgraph.NestedGraphPartition;
-
-import teetime.framework.AbstractConsumerStage;
-
-public class NestedGraphPrinterStage extends AbstractConsumerStage<NestedGraph<Graph>> {
-
-	@Override
-	protected void execute(final NestedGraph<Graph> graph) {
-
-		System.out.println("TOP LEVEL:");
-
-		for (Vertex vertex : graph.getVertices()) {
-			System.out.println(vertex);
-		}
-
-		for (Edge edge : graph.getEdges()) {
-			System.out.println(edge);
-		}
-
-		for (NestedGraphPartition partition : graph.getPartitions()) {
-
-			System.out.println("PARTITION: " + partition.getName());
-
-			for (Vertex vertex : graph.getVerticesForPartition(partition)) {
-				System.out.println(vertex);
-			}
-
-			for (Edge edge : graph.getEdgesForPartition(partition)) {
-				System.out.println(edge);
-			}
-
-		}
-
-	}
-
-}
diff --git a/src/main/java/kieker/analysis/graph/GraphTester.java b/src/main/java/kieker/analysis/graph/GraphTester.java
deleted file mode 100644
index cc5f78aedd5509d215957620f71d152d7ca50d07..0000000000000000000000000000000000000000
--- a/src/main/java/kieker/analysis/graph/GraphTester.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package kieker.analysis.graph;
-
-import kieker.analysis.graph.export.graphml.GraphMLExporter;
-import kieker.analysis.graph.impl.GraphImpl;
-
-public class GraphTester {
-
-	public static void main(final String[] args) {
-
-		Graph graph = new GraphImpl();
-
-		Vertex node1 = graph.addVertex("n1");
-
-		Vertex node2 = graph.addVertex("n2");
-
-		Vertex node3 = graph.addVertex("n3");
-
-		Vertex node4 = graph.addVertex("n4");
-
-		Edge edge12 = node1.addEdge(node2);
-		Edge edge11 = node1.addEdge(node1);
-
-		Edge edge23 = node2.addEdge("e23", node3);
-
-		graph.addEdge("e13", node1, node3);
-
-		Vertex node1snd = graph.getVertex("n1");
-
-		assert node1 == node1snd;
-
-		System.out.println("Master graph");
-
-		for (Vertex vertex : graph.getVertices()) {
-			System.out.println(vertex.getId());
-		}
-
-		for (Edge edge : graph.getEdges()) {
-			System.out.println(edge.getId());
-		}
-
-		// BlueprintsExporter blueprintsExporter = new BlueprintsExporter(graph);
-		// System.out.println(blueprintsExporter.exportGraph());
-
-		// node1snd.remove();
-
-		for (Vertex vertex : graph.getVertices()) {
-			System.out.println(vertex.getId());
-		}
-
-		node1.addChildGraph();
-
-		Vertex node1sub1 = node1.getChildGraph().addVertex("n1::s1");
-		Vertex node1sub2 = node1.getChildGraph().addVertex("n1::s2");
-		Vertex node1sub3 = node1.getChildGraph().addVertex("n1::s3");
-		node1sub3.addEdge("wormhole", node4);
-
-		if (node1.hasChildGraph()) {
-			System.out.println("Node 1 has Child graph");
-		} else {
-			System.out.println("Node 1 does not have a child graph");
-		}
-
-		System.out.println("Node 1's child graph");
-
-		for (Vertex vertex : node1.getChildGraph().getVertices()) {
-			System.out.println(vertex.getId());
-		}
-
-		for (Edge edge : node1.getChildGraph().getEdges()) {
-			System.out.println(edge.getId());
-		}
-
-		System.out.println("Master graph");
-
-		for (Vertex vertex : graph.getVertices()) {
-			System.out.println(vertex.getId());
-		}
-
-		for (Edge edge : graph.getEdges()) {
-			System.out.println(edge.getId());
-		}
-
-		GraphMLExporter graphMLExporter = new GraphMLExporter();
-
-		graphMLExporter.export(graph, System.out);
-
-		// JAXB Test
-
-		//
-		// GraphmlType graphmlType = new GraphmlType();
-		// graphmlType.getKey().add(new KeyType());
-		// GraphType graphType = new GraphType();
-		// graphType.getDataOrNodeOrEdge().add(new NodeType());
-		// graphType.getDataOrNodeOrEdge().add(new NodeType());
-		// graphType.getDataOrNodeOrEdge().add(new EdgeType());
-		// graphmlType.getGraphOrData().add(graphType);
-		//
-		// try {
-		// JAXBContext context = JAXBContext.newInstance(GraphmlType.class);
-		// Marshaller m = context.createMarshaller();
-		// m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
-		//
-		// ObjectFactory objectFactory = new ObjectFactory();
-		// JAXBElement<GraphmlType> element = objectFactory.createGraphml(graphmlType);
-		//
-		// m.marshal(element, System.out);
-		// } catch (JAXBException e) {
-		// // TODO Auto-generated catch block
-		// e.printStackTrace();
-		// }
-
-	}
-
-}
diff --git a/src/main/java/kieker/analysis/graph/export/AbstractExporter.java b/src/main/java/kieker/analysis/graph/export/AbstractExporter.java
deleted file mode 100644
index 16ece18e1b09eb266717fb19f10d65951596e807..0000000000000000000000000000000000000000
--- a/src/main/java/kieker/analysis/graph/export/AbstractExporter.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package kieker.analysis.graph.export;
-
-import kieker.analysis.graph.Edge;
-import kieker.analysis.graph.Graph;
-import kieker.analysis.graph.Vertex;
-
-//TODO unused
-public abstract class AbstractExporter<O> {
-
-	protected Graph graph;
-
-	public AbstractExporter(final Graph graph) {
-		this.graph = graph;
-	}
-
-	public final O export() {
-
-		for (final Vertex vertex : graph.getVertices()) {
-			mapVertex(vertex);
-		}
-
-		for (final Edge edge : graph.getEdges()) {
-			mapEdge(edge);
-		}
-
-		return getExport();
-	}
-
-	protected abstract void mapVertex(Vertex vertex);
-
-	protected abstract void mapEdge(Edge edge);
-
-	protected abstract O getExport();
-}
diff --git a/src/main/java/kieker/analysis/graph/export/AbstractTransformer.java b/src/main/java/kieker/analysis/graph/export/AbstractTransformer.java
deleted file mode 100644
index 0c640f4efc46982eabd823e6772a4e8a77c0dd52..0000000000000000000000000000000000000000
--- a/src/main/java/kieker/analysis/graph/export/AbstractTransformer.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package kieker.analysis.graph.export;
-
-import kieker.analysis.graph.Edge;
-import kieker.analysis.graph.Graph;
-import kieker.analysis.graph.Vertex;
-
-//TODO better name mapper
-public abstract class AbstractTransformer<O> {
-
-	protected Graph graph;
-
-	public AbstractTransformer(final Graph graph) {
-		this.graph = graph;
-	}
-
-	public final O transform() {
-
-		for (final Vertex vertex : graph.getVertices()) {
-			mapVertex(vertex);
-		}
-
-		for (final Edge edge : graph.getEdges()) {
-			mapEdge(edge);
-		}
-
-		return getTransformation();
-	}
-
-	protected abstract void mapVertex(Vertex vertex);
-
-	protected abstract void mapEdge(Edge edge);
-
-	protected abstract O getTransformation();
-}
diff --git a/src/main/java/kieker/analysis/graph/export/BlueprintsExporter.java b/src/main/java/kieker/analysis/graph/export/BlueprintsExporter.java
deleted file mode 100644
index 710777f0f09b86c925a13375f7c4136d5b35b00d..0000000000000000000000000000000000000000
--- a/src/main/java/kieker/analysis/graph/export/BlueprintsExporter.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package kieker.analysis.graph.export;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import com.tinkerpop.blueprints.impls.tg.TinkerGraph;
-
-import kieker.analysis.graph.Direction;
-import kieker.analysis.graph.Edge;
-import kieker.analysis.graph.Graph;
-import kieker.analysis.graph.Vertex;
-
-public class BlueprintsExporter extends AbstractExporter<com.tinkerpop.blueprints.Graph> {
-
-	private final com.tinkerpop.blueprints.Graph exportGraph = new TinkerGraph();
-	private final Map<Vertex, com.tinkerpop.blueprints.Vertex> mappedVertices = new HashMap<>();
-
-	private static final String LABEL_PROPERTY = "label";
-
-	public BlueprintsExporter(final Graph graph) {
-		super(graph);
-	}
-
-	@Override
-	protected void mapVertex(final Vertex vertex) {
-		com.tinkerpop.blueprints.Vertex mappedVertex = exportGraph.addVertex(vertex.getId());
-		mappedVertices.put(vertex, mappedVertex);
-		for (final String propertyKey : vertex.getPropertyKeys()) {
-			mappedVertex.setProperty(propertyKey, vertex.getProperty(propertyKey));
-		}
-
-	}
-
-	@Override
-	protected void mapEdge(final Edge edge) {
-		final com.tinkerpop.blueprints.Vertex mappedInVertex = mappedVertices.get(edge.getVertex(Direction.IN));
-		final com.tinkerpop.blueprints.Vertex mappedOutVertex = mappedVertices.get(edge.getVertex(Direction.OUT));
-		String label = edge.getProperty(LABEL_PROPERTY);
-		if (label == null) {
-			label = "";
-		}
-		com.tinkerpop.blueprints.Edge mappedEdge = exportGraph.addEdge(edge.getId(), mappedOutVertex, mappedInVertex, label);
-		for (final String propertyKey : edge.getPropertyKeys()) {
-			mappedEdge.setProperty(propertyKey, edge.getProperty(propertyKey));
-		}
-	}
-
-	@Override
-	protected com.tinkerpop.blueprints.Graph getExport() {
-		return exportGraph;
-	}
-
-}
diff --git a/src/main/java/kieker/analysis/graph/export/Exporter.java b/src/main/java/kieker/analysis/graph/export/Exporter.java
deleted file mode 100644
index 7acabe6c980b5ef0427afb12aadeed56ccf98c58..0000000000000000000000000000000000000000
--- a/src/main/java/kieker/analysis/graph/export/Exporter.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package kieker.analysis.graph.export;
-
-import kieker.analysis.graph.Graph;
-
-//TODO maybe no interface required
-public interface Exporter<O> {
-
-	public O export(Graph graph);
-
-}
diff --git a/src/main/java/kieker/analysis/graph/export/dot/DotExporter.java b/src/main/java/kieker/analysis/graph/export/dot/DotExporter.java
deleted file mode 100644
index 315199883f2b304f708e78ec439dcd83f81fb7e8..0000000000000000000000000000000000000000
--- a/src/main/java/kieker/analysis/graph/export/dot/DotExporter.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package kieker.analysis.graph.export.dot;
-
-import java.io.OutputStream;
-
-import kieker.analysis.graph.Graph;
-
-public class DotExporter {
-
-	public void export(final Graph graph, final OutputStream outputStream) {
-
-		GraphTransformer graphTransformer = new GraphTransformer(graph);
-		// TODO Receiving a dot object would be (maybe) better
-		String dotString = graphTransformer.transform();
-
-	}
-
-}
diff --git a/src/main/java/kieker/analysis/graph/export/dot/GraphTransformer.java b/src/main/java/kieker/analysis/graph/export/dot/GraphTransformer.java
deleted file mode 100644
index 18ff2f6a2df32e14c56dc066be58e17ca5276bf0..0000000000000000000000000000000000000000
--- a/src/main/java/kieker/analysis/graph/export/dot/GraphTransformer.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package kieker.analysis.graph.export.dot;
-
-import kieker.analysis.graph.Direction;
-import kieker.analysis.graph.Edge;
-import kieker.analysis.graph.Graph;
-import kieker.analysis.graph.Vertex;
-import kieker.analysis.graph.export.AbstractTransformer;
-import kieker.analysis.util.DotBuilder;
-
-public class GraphTransformer extends AbstractTransformer<String> {
-
-	private final DotBuilder dotBuilder;
-
-	public GraphTransformer(final Graph graph) {
-		super(graph);
-		dotBuilder = new DotBuilder(graph.getName());
-	}
-
-	@Override
-	protected void mapVertex(final Vertex vertex) {
-		if (vertex.hasChildGraph()) {
-			Graph childGraph = vertex.getChildGraph();
-			GraphTransformer graphTransformer = new GraphTransformer(childGraph);
-			String childGraphString = graphTransformer.transform();
-			// TODO We need a subgraph cluster_XYZ { ... }
-			// TODO dotBuilder.addCluster();
-		} else {
-			dotBuilder.addNode(vertex.getId().toString());
-			// TODO Add style, label, etc
-			// TODO Handle child graph
-		}
-
-	}
-
-	@Override
-	protected void mapEdge(final Edge edge) {
-		String sourceId = edge.getVertex(Direction.OUT).getId().toString();
-		String targetId = edge.getVertex(Direction.IN).getId().toString();
-		dotBuilder.addEdge(sourceId, targetId);
-		// TODO Add style, label, etc
-
-	}
-
-	@Override
-	protected String getTransformation() {
-		return dotBuilder.get();
-	}
-
-}
diff --git a/src/main/java/kieker/analysis/graph/export/graphml/GraphMLExporter.java b/src/main/java/kieker/analysis/graph/export/graphml/GraphMLExporter.java
deleted file mode 100644
index 853efca083866470d6b738e63f0aec010887cdc7..0000000000000000000000000000000000000000
--- a/src/main/java/kieker/analysis/graph/export/graphml/GraphMLExporter.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package kieker.analysis.graph.export.graphml;
-
-import java.io.OutputStream;
-
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBElement;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.Marshaller;
-
-import org.graphdrawing.graphml.GraphType;
-import org.graphdrawing.graphml.GraphmlType;
-import org.graphdrawing.graphml.ObjectFactory;
-
-import kieker.analysis.graph.Graph;
-
-public class GraphMLExporter {
-
-	private static final Boolean FORMATTED_OUTPUT = Boolean.TRUE;
-
-	public void export(final Graph graph, final OutputStream outputStream) {
-
-		GraphmlType graphmlType = new GraphmlType();
-
-		GraphTypeTransformer graphTypeTransformer = new GraphTypeTransformer(graph);
-		GraphType graphType = graphTypeTransformer.transform();
-
-		graphmlType.getGraphOrData().add(graphType);
-
-		try {
-			JAXBContext context = JAXBContext.newInstance(GraphmlType.class);
-			Marshaller marshaller = context.createMarshaller();
-			marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, FORMATTED_OUTPUT);
-
-			ObjectFactory objectFactory = new ObjectFactory();
-			JAXBElement<GraphmlType> rootElement = objectFactory.createGraphml(graphmlType);
-
-			marshaller.marshal(rootElement, outputStream);
-		} catch (JAXBException e) {
-			// TODO Auto-generated catch block
-			// TODO wrap exception
-			e.printStackTrace();
-		}
-
-	}
-
-}
diff --git a/src/main/java/kieker/analysis/graph/export/graphml/GraphTypeTransformer.java b/src/main/java/kieker/analysis/graph/export/graphml/GraphTypeTransformer.java
deleted file mode 100644
index b9367e7cd46183c1b66869ca4114cde59840284c..0000000000000000000000000000000000000000
--- a/src/main/java/kieker/analysis/graph/export/graphml/GraphTypeTransformer.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package kieker.analysis.graph.export.graphml;
-
-import org.graphdrawing.graphml.EdgeType;
-import org.graphdrawing.graphml.GraphType;
-import org.graphdrawing.graphml.NodeType;
-
-import kieker.analysis.graph.Edge;
-import kieker.analysis.graph.Graph;
-import kieker.analysis.graph.Vertex;
-import kieker.analysis.graph.export.AbstractTransformer;
-
-public class GraphTypeTransformer extends AbstractTransformer<GraphType> {
-
-	private final GraphType graphType;
-
-	public GraphTypeTransformer(final Graph graph) {
-		super(graph);
-		graphType = new GraphType();
-	}
-
-	@Override
-	protected void mapVertex(final Vertex vertex) {
-
-		NodeType nodeType = new NodeType();
-		// TODO Map Properties + id
-
-		if (vertex.hasChildGraph()) {
-			Graph childGraph = vertex.getChildGraph();
-			GraphTypeTransformer graphTypeTransformer = new GraphTypeTransformer(childGraph);
-			GraphType childGraphType = graphTypeTransformer.transform();
-			nodeType.setGraph(childGraphType);
-		}
-
-		graphType.getDataOrNodeOrEdge().add(nodeType);
-	}
-
-	@Override
-	protected void mapEdge(final Edge edge) {
-		EdgeType edgeType = new EdgeType();
-		// TODO Map Properties + id + source/target
-		graphType.getDataOrNodeOrEdge().add(edgeType);
-	}
-
-	@Override
-	protected GraphType getTransformation() {
-		return graphType;
-	}
-
-}
diff --git a/src/main/java/kieker/analysis/graph/traversal/FlatGraphTraverser.java b/src/main/java/kieker/analysis/graph/traversal/FlatGraphTraverser.java
deleted file mode 100644
index 182bad4333d775b6b36c8a116b8c75571adb113f..0000000000000000000000000000000000000000
--- a/src/main/java/kieker/analysis/graph/traversal/FlatGraphTraverser.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package kieker.analysis.graph.traversal;
-
-import kieker.analysis.graph.Edge;
-import kieker.analysis.graph.Graph;
-import kieker.analysis.graph.Vertex;
-
-public class FlatGraphTraverser {
-
-	public void traverse(final Graph graph) {
-
-		for (Vertex vertex : graph.getVertices()) {
-			// TODO call (vertex) visitor
-		}
-
-		for (Edge edge : graph.getEdges()) {
-			// TODO Call (edge)visitor
-		}
-
-	}
-
-}
diff --git a/src/main/java/kieker/analysis/graph/traversal/NestedGraphTraverser.java b/src/main/java/kieker/analysis/graph/traversal/NestedGraphTraverser.java
deleted file mode 100644
index 046ac6cec66f674c942448d60cc49479abdcf969..0000000000000000000000000000000000000000
--- a/src/main/java/kieker/analysis/graph/traversal/NestedGraphTraverser.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package kieker.analysis.graph.traversal;
-
-import kieker.analysis.graph.Edge;
-import kieker.analysis.graph.Graph;
-import kieker.analysis.graph.Vertex;
-
-//TODO unused
-public class NestedGraphTraverser {
-
-	public void traverse(final Graph graph) {
-
-		for (Vertex vertex : graph.getVertices()) {
-			// TODO call (vertex) visitor
-
-			NestedGraphTraverser childGraphTraverser = new NestedGraphTraverser();
-			// Visitor vistor;
-			// childGraphTraverser.addVisitor(visitor);
-			childGraphTraverser.traverse(graph);
-			// visitor.
-		}
-
-		for (Edge edge : graph.getEdges()) {
-			// TODO Call (edge)visitor
-		}
-
-	}
-
-}
diff --git a/src/main/java/kieker/analysis/trace/graphoutput/DotGraphWriter.java b/src/main/java/kieker/analysis/trace/graphoutput/DotGraphWriter.java
deleted file mode 100644
index 0f88302f0bf4a5e0e91d410627fcdfda96e4623e..0000000000000000000000000000000000000000
--- a/src/main/java/kieker/analysis/trace/graphoutput/DotGraphWriter.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package kieker.analysis.trace.graphoutput;
-
-import java.io.BufferedWriter;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.util.HashMap;
-import java.util.Map;
-
-import com.tinkerpop.blueprints.Direction;
-import com.tinkerpop.blueprints.Edge;
-import com.tinkerpop.blueprints.Graph;
-import com.tinkerpop.blueprints.Vertex;
-
-import kieker.analysis.util.DotBuilder;
-import kieker.analysis.util.graph.NamedGraph;
-
-import teetime.framework.AbstractConsumerStage;
-
-public class DotGraphWriter extends AbstractConsumerStage<NamedGraph<Graph>> {
-
-	private final String outputDir;
-
-	public DotGraphWriter(final String outputDir) {
-		this.outputDir = outputDir;
-	}
-
-	@Override
-	protected void execute(final NamedGraph<Graph> graph) {
-		final String dotGraph = createDotGraph(graph);
-		final String fileName = outputDir + "/" + graph.getFileName() + ".dot";
-
-		try {
-			writeDotGraphFile(dotGraph, fileName);
-		} catch (IOException e) {
-			throw new IllegalStateException(e);
-		}
-	}
-
-	private String createDotGraph(final Graph graph) {
-
-		DotBuilder dotGraph = new DotBuilder();
-
-		Map<String, String> nodeProperties = new HashMap<>();
-		nodeProperties.put("shape", "none");
-
-		dotGraph.setDefaultNodeProperties(nodeProperties);
-
-		for (Vertex vertex : graph.getVertices()) {
-			String label = vertex.getProperty("label");
-			dotGraph.addNode(String.valueOf(vertex.getId()), label);
-		}
-
-		for (Edge edge : graph.getEdges()) {
-			String source = edge.getVertex(Direction.OUT).getId().toString();
-			String target = edge.getVertex(Direction.IN).getId().toString();
-			dotGraph.addEdge(source, target, edge.getLabel());
-		}
-
-		return dotGraph.get();
-	}
-
-	private void writeDotGraphFile(final String dotGraph, final String fileName) throws IOException {
-
-		final OutputStream outputStream = new FileOutputStream(fileName);
-
-		final Writer writer = new BufferedWriter(new OutputStreamWriter(outputStream, "utf-8"));
-		writer.write(dotGraph);
-		writer.close();
-
-	}
-}
diff --git a/src/main/java/kieker/analysis/trace/graphoutput/DotTraceGraphFileWriterStage.java b/src/main/java/kieker/analysis/trace/graphoutput/DotTraceGraphFileWriterStage.java
new file mode 100644
index 0000000000000000000000000000000000000000..a030d92ae43839f9f914ef65d769532991936c35
--- /dev/null
+++ b/src/main/java/kieker/analysis/trace/graphoutput/DotTraceGraphFileWriterStage.java
@@ -0,0 +1,13 @@
+package kieker.analysis.trace.graphoutput;
+
+import kieker.analysis.util.graph.export.dot.DotFileWriterStage;
+import kieker.analysis.util.graph.util.dot.attributes.DotNodeAttribute;
+
+public class DotTraceGraphFileWriterStage extends DotFileWriterStage {
+
+	public DotTraceGraphFileWriterStage(final String outputDirectory) {
+		super(outputDirectory);
+		exportConfiguration.getDefaultNodeAttributes().put(DotNodeAttribute.SHAPE, (g -> "none"));
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/trace/graphoutput/GraphMLWriter.java b/src/main/java/kieker/analysis/trace/graphoutput/GraphMLWriter.java
deleted file mode 100644
index eede0b283b3fbb3b441616930b665967cd473bc7..0000000000000000000000000000000000000000
--- a/src/main/java/kieker/analysis/trace/graphoutput/GraphMLWriter.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package kieker.analysis.trace.graphoutput;
-
-import java.io.IOException;
-
-import com.tinkerpop.blueprints.Graph;
-
-import kieker.analysis.util.graph.NamedGraph;
-
-import teetime.framework.AbstractConsumerStage;
-
-public class GraphMLWriter extends AbstractConsumerStage<NamedGraph<Graph>> {
-
-	private final String outputDir;
-
-	public GraphMLWriter(final String outputDir) {
-		this.outputDir = outputDir;
-	}
-
-	@Override
-	protected void execute(final NamedGraph<Graph> graph) {
-
-		String outputFile = outputDir + "/" + graph.getFileName() + ".xml";
-
-		com.tinkerpop.blueprints.util.io.graphml.GraphMLWriter writer = new com.tinkerpop.blueprints.util.io.graphml.GraphMLWriter(graph);
-		writer.setNormalize(true);
-
-		try {
-			writer.outputGraph(outputFile);
-		} catch (IOException e) {
-			throw new IllegalStateException(e);
-		}
-
-	}
-
-}
diff --git a/src/main/java/kieker/analysis/trace/traversal/AbstractTraceToGraphTransformer.java b/src/main/java/kieker/analysis/trace/traversal/AbstractTraceToGraphTransformer.java
index 77fb05acf09022826909142f70e5857de7bfb834..1606c373c9a1706108c1974e2bdbe950191d2c5c 100644
--- a/src/main/java/kieker/analysis/trace/traversal/AbstractTraceToGraphTransformer.java
+++ b/src/main/java/kieker/analysis/trace/traversal/AbstractTraceToGraphTransformer.java
@@ -1,11 +1,10 @@
 package kieker.analysis.trace.traversal;
 
-import com.tinkerpop.blueprints.Edge;
-import com.tinkerpop.blueprints.Graph;
-import com.tinkerpop.blueprints.Vertex;
-import com.tinkerpop.blueprints.impls.tg.TinkerGraph;
-
 import kieker.analysis.domain.AbstractOperationCall;
+import kieker.analysis.util.graph.Edge;
+import kieker.analysis.util.graph.Graph;
+import kieker.analysis.util.graph.Vertex;
+import kieker.analysis.util.graph.impl.GraphImpl;
 
 public abstract class AbstractTraceToGraphTransformer<C extends AbstractOperationCall<C>> extends OperationCallVisitor<C> {
 
@@ -18,7 +17,7 @@ public abstract class AbstractTraceToGraphTransformer<C extends AbstractOperatio
 
 	public AbstractTraceToGraphTransformer(final C rootOperartionCall) {
 		super();
-		this.graph = new TinkerGraph();
+		this.graph = new GraphImpl();
 		this.rootOperationCall = rootOperartionCall;
 	}
 
@@ -54,7 +53,8 @@ public abstract class AbstractTraceToGraphTransformer<C extends AbstractOperatio
 
 		final Vertex rootVertex = graph.addVertex("Entry");
 		rootVertex.setProperty("label", "'Entry'");
-		graph.addEdge(null, rootVertex, realRootVertex, "1.");
+		Edge edge = graph.addEdge(null, rootVertex, realRootVertex);
+		edge.setProperty("label", "1.");
 
 	}
 
diff --git a/src/main/java/kieker/analysis/trace/traversal/AggrTraceToGraphTransformer.java b/src/main/java/kieker/analysis/trace/traversal/AggrTraceToGraphTransformer.java
index d8cae5ea43e9202f8e33404442881b22bde07164..51f761a618bc24251ac075346d0bc011fbc95889 100644
--- a/src/main/java/kieker/analysis/trace/traversal/AggrTraceToGraphTransformer.java
+++ b/src/main/java/kieker/analysis/trace/traversal/AggrTraceToGraphTransformer.java
@@ -1,10 +1,9 @@
 package kieker.analysis.trace.traversal;
 
-import com.tinkerpop.blueprints.Edge;
-import com.tinkerpop.blueprints.Vertex;
-
 import kieker.analysis.domain.AggregatedOperationCall;
 import kieker.analysis.util.NameConverter;
+import kieker.analysis.util.graph.Edge;
+import kieker.analysis.util.graph.Vertex;
 
 public class AggrTraceToGraphTransformer extends AbstractTraceToGraphTransformer<AggregatedOperationCall> {
 
@@ -49,7 +48,9 @@ public class AggrTraceToGraphTransformer extends AbstractTraceToGraphTransformer
 			return null;
 		}
 
-		return graph.addEdge(null, parentVertex, thisVertex, String.valueOf(operationCall.getOrderIndex() + 1) + '.');
+		final Edge edge = graph.addEdge(null, parentVertex, thisVertex);
+		edge.setProperty("label", String.valueOf(operationCall.getOrderIndex() + 1) + '.');
+		return edge;
 	}
 
 }
diff --git a/src/main/java/kieker/analysis/trace/traversal/AggrTraceTraverserStage.java b/src/main/java/kieker/analysis/trace/traversal/AggrTraceTraverserStage.java
index 7d24977a6cdfaf7f1ac7e2d1fb9089bc59f10a61..eb29c6fab6e48524226097aabd2a4c0ff1f5c1db 100644
--- a/src/main/java/kieker/analysis/trace/traversal/AggrTraceTraverserStage.java
+++ b/src/main/java/kieker/analysis/trace/traversal/AggrTraceTraverserStage.java
@@ -1,14 +1,12 @@
 package kieker.analysis.trace.traversal;
 
-import com.tinkerpop.blueprints.Graph;
-
 import kieker.analysis.domain.AggregatedOperationCall;
 import kieker.analysis.domain.AggregatedTrace;
-import kieker.analysis.util.graph.NamedGraph;
+import kieker.analysis.util.graph.Graph;
 
 import teetime.stage.basic.AbstractTransformation;
 
-public class AggrTraceTraverserStage extends AbstractTransformation<AggregatedTrace, NamedGraph<Graph>> {
+public class AggrTraceTraverserStage extends AbstractTransformation<AggregatedTrace, Graph> {
 
 	@Override
 	protected void execute(final AggregatedTrace trace) {
@@ -21,7 +19,8 @@ public class AggrTraceTraverserStage extends AbstractTransformation<AggregatedTr
 
 		final String name = "aggr-trace-" + trace.hashCode();
 
-		final NamedGraph<Graph> graph = new NamedGraph<>(name, name, aggrTrace2Blueprint.getGraph());
+		final Graph graph = aggrTrace2Blueprint.getGraph();
+		graph.setName(name);
 
 		this.getOutputPort().send(graph);
 	}
diff --git a/src/main/java/kieker/analysis/trace/traversal/TraceToGraphTransformer.java b/src/main/java/kieker/analysis/trace/traversal/TraceToGraphTransformer.java
index e1f54798edebc5843c9cefe00ae493dae57d85dd..5fa9f5900e614963ae305821850e0ba3d07e4c6d 100644
--- a/src/main/java/kieker/analysis/trace/traversal/TraceToGraphTransformer.java
+++ b/src/main/java/kieker/analysis/trace/traversal/TraceToGraphTransformer.java
@@ -1,10 +1,9 @@
 package kieker.analysis.trace.traversal;
 
-import com.tinkerpop.blueprints.Edge;
-import com.tinkerpop.blueprints.Vertex;
-
 import kieker.analysis.domain.OperationCall;
 import kieker.analysis.util.NameConverter;
+import kieker.analysis.util.graph.Edge;
+import kieker.analysis.util.graph.Vertex;
 
 public class TraceToGraphTransformer extends AbstractTraceToGraphTransformer<OperationCall> {
 
@@ -48,7 +47,9 @@ public class TraceToGraphTransformer extends AbstractTraceToGraphTransformer<Ope
 			return null;
 		}
 
-		return graph.addEdge(null, parentVertex, thisVertex, String.valueOf(operationCall.getOrderIndex() + 1) + '.');
+		final Edge edge = graph.addEdge(null, parentVertex, thisVertex);
+		edge.setProperty("label", String.valueOf(operationCall.getOrderIndex() + 1) + '.');
+		return edge;
 	}
 
 }
diff --git a/src/main/java/kieker/analysis/trace/traversal/TraceTraverserStage.java b/src/main/java/kieker/analysis/trace/traversal/TraceTraverserStage.java
index 3212e0a0a7a2b57034ff897244e867d263bc1228..5a0322b51399cc2b961ec95b56f331c9a15b48ca 100644
--- a/src/main/java/kieker/analysis/trace/traversal/TraceTraverserStage.java
+++ b/src/main/java/kieker/analysis/trace/traversal/TraceTraverserStage.java
@@ -1,14 +1,12 @@
 package kieker.analysis.trace.traversal;
 
-import com.tinkerpop.blueprints.Graph;
-
 import kieker.analysis.domain.OperationCall;
 import kieker.analysis.domain.Trace;
-import kieker.analysis.util.graph.NamedGraph;
+import kieker.analysis.util.graph.Graph;
 
 import teetime.stage.basic.AbstractTransformation;
 
-public class TraceTraverserStage extends AbstractTransformation<Trace, NamedGraph<Graph>> {
+public class TraceTraverserStage extends AbstractTransformation<Trace, Graph> {
 
 	@Override
 	protected void execute(final Trace trace) {
@@ -21,7 +19,8 @@ public class TraceTraverserStage extends AbstractTransformation<Trace, NamedGrap
 
 		final String name = "trace-" + trace.hashCode();
 
-		final NamedGraph<Graph> graph = new NamedGraph<>(name, name, traceToGraph.getGraph());
+		final Graph graph = traceToGraph.getGraph();
+		graph.setName(name);
 
 		this.getOutputPort().send(graph);
 	}
diff --git a/src/main/java/kieker/analysis/util/AbstractCombinerStage.java b/src/main/java/kieker/analysis/util/AbstractCombinerStage.java
new file mode 100644
index 0000000000000000000000000000000000000000..95dafe9c0040a71a0e40642980c9fd7a7e237900
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/AbstractCombinerStage.java
@@ -0,0 +1,44 @@
+package kieker.analysis.util;
+
+import java.util.LinkedList;
+import java.util.Queue;
+
+import teetime.framework.AbstractStage;
+import teetime.framework.InputPort;
+
+public abstract class AbstractCombinerStage<I, J> extends AbstractStage {
+
+	protected final InputPort<I> inputPort1 = this.createInputPort();
+	protected final InputPort<J> inputPort2 = this.createInputPort();
+
+	private final Queue<I> elements1 = new LinkedList<>();
+	private final Queue<J> elements2 = new LinkedList<>();
+
+	public final InputPort<I> getInputPort1() {
+		return this.inputPort1;
+	}
+
+	public final InputPort<J> getInputPort2() {
+		return this.inputPort2;
+	}
+
+	@Override
+	protected void execute() {
+
+		final I element1 = this.getInputPort1().receive();
+		if (element1 != null) {
+			elements1.add(element1);
+		}
+		final J element2 = this.getInputPort2().receive();
+		if (element2 != null) {
+			elements2.add(element2);
+		}
+
+		if (elements1.size() > 0 && elements2.size() > 0) {
+			this.combine(elements1.poll(), elements2.poll());
+		}
+	}
+
+	protected abstract void combine(final I element1, final J element2);
+
+}
diff --git a/src/main/java/kieker/analysis/util/DotBuilder.java b/src/main/java/kieker/analysis/util/DotBuilder.java
deleted file mode 100644
index f2a80ddeb5af88607ffd9b4ed18edc97a9325cee..0000000000000000000000000000000000000000
--- a/src/main/java/kieker/analysis/util/DotBuilder.java
+++ /dev/null
@@ -1,129 +0,0 @@
-package kieker.analysis.util;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import com.google.common.base.Joiner;
-
-/**
- * Simple class for building and representing dot graph files.
- *
- * @author Sören Henning
- *
- */
-public class DotBuilder {
-
-	private final String start;
-	private final String end = "}";
-	private final StringBuilder body = new StringBuilder();
-
-	private Map<String, String> defaultNodeProperties;
-	private Map<String, String> defaultEdgeProperties;
-	private Map<String, String> defaultProperties;
-
-	public DotBuilder() {
-		this("G");
-	}
-
-	public DotBuilder(final String name) {
-		start = "digraph " + name + " {\n";
-	}
-
-	public DotBuilder(final String name, final Map<String, String> defaultNodeProperties, final Map<String, String> defaultEdgeProperties) {
-		this(name);
-		this.defaultNodeProperties = defaultNodeProperties;
-		this.defaultEdgeProperties = defaultEdgeProperties;
-	}
-
-	public DotBuilder(final String name, final Map<String, String> defaultNodeProperties, final Map<String, String> defaultEdgeProperties,
-			final Map<String, String> defaultProperties) {
-		this(name, defaultNodeProperties, defaultEdgeProperties);
-		this.defaultProperties = defaultProperties;
-	}
-
-	public void setDefaultNodeProperties(final Map<String, String> defaultNodeProperties) {
-		this.defaultNodeProperties = defaultNodeProperties;
-	}
-
-	public void setDefaultEdgeProperties(final Map<String, String> defaultEdgeProperties) {
-		this.defaultEdgeProperties = defaultEdgeProperties;
-	}
-
-	public void setDefaultProperties(final Map<String, String> defaultProperties) {
-		this.defaultProperties = defaultProperties;
-	}
-
-	public String get() {
-		return start + body.toString() + end;
-	}
-
-	@Override
-	public String toString() {
-		return get();
-	}
-
-	public void addNode(final String id) {
-		addNode(id, new HashMap<>());
-	}
-
-	public void addNode(final String id, final String label) {
-		Map<String, String> properties = new HashMap<String, String>();
-		properties.put("label", label);
-		addNode(id, properties);
-	}
-
-	public void addNode(final String id, final Map<String, String> properties) {
-		addElement('"' + id + '"', extendNodeProperties(properties));
-	}
-
-	public void addEdge(final String source, final String target) {
-		addEdge(source, target, new HashMap<>());
-	}
-
-	public void addEdge(final String source, final String target, final String label) {
-		Map<String, String> properties = new HashMap<String, String>();
-		properties.put("label", label);
-		addEdge(source, target, properties);
-	}
-
-	public void addEdge(final String source, final String target, final Map<String, String> properties) {
-		addElement('"' + source + '"' + " -> " + '"' + target + '"', extendEdgeProperties(properties));
-	}
-
-	private void addElement(final String element, final Map<String, String> properties) {
-		body.append(element);
-		if (properties != null && !properties.isEmpty()) {
-			body.append(" [");
-			Joiner.on("\", ").withKeyValueSeparator("=\"").appendTo(body, properties);
-			body.append("\"]");
-		}
-		body.append('\n');
-	}
-
-	private Map<String, String> extendNodeProperties(final Map<String, String> properties) {
-		return extendElementProperties(properties, defaultNodeProperties);
-	}
-
-	private Map<String, String> extendEdgeProperties(final Map<String, String> properties) {
-		return extendElementProperties(properties, defaultEdgeProperties);
-	}
-
-	private Map<String, String> extendElementProperties(final Map<String, String> properties, final Map<String, String> defaultElementProperties) {
-
-		if (defaultElementProperties != null) {
-			for (Entry<String, String> property : defaultElementProperties.entrySet()) {
-				properties.putIfAbsent(property.getKey(), property.getValue());
-			}
-		}
-
-		if (defaultProperties != null) {
-			for (Entry<String, String> property : defaultProperties.entrySet()) {
-				properties.putIfAbsent(property.getKey(), property.getValue());
-			}
-		}
-
-		return properties;
-	}
-
-}
diff --git a/src/main/java/kieker/analysis/util/FunctionStage.java b/src/main/java/kieker/analysis/util/FunctionStage.java
new file mode 100644
index 0000000000000000000000000000000000000000..90e8a4ef30bca390bdf1ff8c8f116de0461c99d7
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/FunctionStage.java
@@ -0,0 +1,30 @@
+package kieker.analysis.util;
+
+import java.util.function.Function;
+
+import teetime.stage.basic.AbstractTransformation;
+
+public class FunctionStage<I, O> extends AbstractTransformation<I, O> {
+
+	private Function<I, O> function;
+
+	public FunctionStage(final Function<I, O> function) {
+		super();
+		this.function = function;
+	}
+
+	public Function<I, O> getFunction() {
+		return function;
+	}
+
+	public void setFunction(final Function<I, O> function) {
+		this.function = function;
+	}
+
+	@Override
+	protected void execute(final I element) {
+		final O transformedElement = function.apply(element);
+		this.getOutputPort().send(transformedElement);
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/JAXBMarshalStage.java b/src/main/java/kieker/analysis/util/JAXBMarshalStage.java
new file mode 100644
index 0000000000000000000000000000000000000000..fe7137aee94a9e0740d7fd18bde21606c33eb9e7
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/JAXBMarshalStage.java
@@ -0,0 +1,51 @@
+package kieker.analysis.util;
+
+import java.io.OutputStream;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+
+/**
+ * This stage marshals the content tree rooted at an incoming element at the
+ * first input port into an output stream at the second input port.
+ *
+ * A class object has to be passed at creation. Only elements of this type
+ * wrapped in a {@code JAXBElement} could be marshaled.
+ *
+ * @author Sören Henning
+ *
+ */
+public class JAXBMarshalStage<T> extends AbstractCombinerStage<JAXBElement<T>, OutputStream> {
+
+	private static final Boolean FORMATTED_OUTPUT_DEFAULT = Boolean.TRUE;
+
+	private final Marshaller marshaller;
+
+	public JAXBMarshalStage(final Class<T> elementsClass) {
+		this(elementsClass, FORMATTED_OUTPUT_DEFAULT);
+	}
+
+	public JAXBMarshalStage(final Class<T> elementsClass, final Boolean formattedOutput) {
+		try {
+			this.marshaller = JAXBContext.newInstance(elementsClass).createMarshaller();
+			marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, formattedOutput);
+		} catch (JAXBException e) {
+			// TODO Exception
+			throw new IllegalStateException(e);
+		}
+	}
+
+	@Override
+	protected void combine(final JAXBElement<T> jaxbElement, final OutputStream outputStream) {
+
+		try {
+			marshaller.marshal(jaxbElement, outputStream);
+		} catch (JAXBException e) {
+			// TODO Exception
+			throw new IllegalStateException("The received element could not be marshalled.", e);
+		}
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/NamedGraph.java b/src/main/java/kieker/analysis/util/blueprintsgraph/NamedGraph.java
similarity index 93%
rename from src/main/java/kieker/analysis/util/graph/NamedGraph.java
rename to src/main/java/kieker/analysis/util/blueprintsgraph/NamedGraph.java
index 1025ec8a71b5f26cd0de2ae1f546c8951f01dc7f..f922975fe94a2f9d262c10b42274bb8677fb7316 100644
--- a/src/main/java/kieker/analysis/util/graph/NamedGraph.java
+++ b/src/main/java/kieker/analysis/util/blueprintsgraph/NamedGraph.java
@@ -1,4 +1,4 @@
-package kieker.analysis.util.graph;
+package kieker.analysis.util.blueprintsgraph;
 
 import com.tinkerpop.blueprints.Graph;
 import com.tinkerpop.blueprints.util.wrappers.wrapped.WrappedGraph;
diff --git a/src/main/java/kieker/analysis/graph/Direction.java b/src/main/java/kieker/analysis/util/graph/Direction.java
similarity index 90%
rename from src/main/java/kieker/analysis/graph/Direction.java
rename to src/main/java/kieker/analysis/util/graph/Direction.java
index d10ff42b72b715e507b324d8677a76321c0cd925..666442f6602bb2ff7c72c96da8fb65b856128c4c 100644
--- a/src/main/java/kieker/analysis/graph/Direction.java
+++ b/src/main/java/kieker/analysis/util/graph/Direction.java
@@ -1,4 +1,4 @@
-package kieker.analysis.graph;
+package kieker.analysis.util.graph;
 
 /**
  * Direction is used to denote the direction of an edge or location of a vertex on an edge.
diff --git a/src/main/java/kieker/analysis/graph/Edge.java b/src/main/java/kieker/analysis/util/graph/Edge.java
similarity index 50%
rename from src/main/java/kieker/analysis/graph/Edge.java
rename to src/main/java/kieker/analysis/util/graph/Edge.java
index 75fdbd09e8c8308323a3d12a12c2dcc848c76be8..a75ae7fcbfeab12cc9afabd27a6413dbad7d8613 100644
--- a/src/main/java/kieker/analysis/graph/Edge.java
+++ b/src/main/java/kieker/analysis/util/graph/Edge.java
@@ -1,6 +1,6 @@
-package kieker.analysis.graph;
+package kieker.analysis.util.graph;
 
-public interface Edge extends Element {
+public interface Edge extends GraphElement {
 
 	public Vertex getVertex(Direction direction) throws IllegalArgumentException;
 
diff --git a/src/main/java/kieker/analysis/graph/Element.java b/src/main/java/kieker/analysis/util/graph/Element.java
similarity index 75%
rename from src/main/java/kieker/analysis/graph/Element.java
rename to src/main/java/kieker/analysis/util/graph/Element.java
index 9682cead451b9861c1a504c94fd9474ebe5a02c8..81257b4f8028473894f8708f94485b0a5f03e0e4 100644
--- a/src/main/java/kieker/analysis/graph/Element.java
+++ b/src/main/java/kieker/analysis/util/graph/Element.java
@@ -1,4 +1,4 @@
-package kieker.analysis.graph;
+package kieker.analysis.util.graph;
 
 import java.util.Set;
 
@@ -12,7 +12,4 @@ public abstract interface Element {
 
 	public <T> T removeProperty(String key);
 
-	public void remove();
-
-	public Object getId();
 }
diff --git a/src/main/java/kieker/analysis/graph/Graph.java b/src/main/java/kieker/analysis/util/graph/Graph.java
similarity index 83%
rename from src/main/java/kieker/analysis/graph/Graph.java
rename to src/main/java/kieker/analysis/util/graph/Graph.java
index 36593bf60b293eec50e563202f7613b5d44470cd..d93e6c8c3976ceebed63d89caf34bad40fbdb3de 100644
--- a/src/main/java/kieker/analysis/graph/Graph.java
+++ b/src/main/java/kieker/analysis/util/graph/Graph.java
@@ -1,6 +1,6 @@
-package kieker.analysis.graph;
+package kieker.analysis.util.graph;
 
-public interface Graph {
+public interface Graph extends Element {
 
 	public String getName();
 
diff --git a/src/main/java/kieker/analysis/util/graph/GraphElement.java b/src/main/java/kieker/analysis/util/graph/GraphElement.java
new file mode 100644
index 0000000000000000000000000000000000000000..2fa271d5ba691c965a24759d3fd2cff9eebbb181
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/GraphElement.java
@@ -0,0 +1,8 @@
+package kieker.analysis.util.graph;
+
+public abstract interface GraphElement extends Element {
+
+	public void remove();
+
+	public Object getId();
+}
diff --git a/src/main/java/kieker/analysis/graph/Vertex.java b/src/main/java/kieker/analysis/util/graph/Vertex.java
similarity index 72%
rename from src/main/java/kieker/analysis/graph/Vertex.java
rename to src/main/java/kieker/analysis/util/graph/Vertex.java
index 788a08e321be3f2a50365c99003127f277f09afa..7e12eefdfc50d729c0f8203c64d4f1f7c28a97c5 100644
--- a/src/main/java/kieker/analysis/graph/Vertex.java
+++ b/src/main/java/kieker/analysis/util/graph/Vertex.java
@@ -1,6 +1,6 @@
-package kieker.analysis.graph;
+package kieker.analysis.util.graph;
 
-public interface Vertex extends Element {
+public interface Vertex extends GraphElement {
 
 	public Graph addChildGraph();
 
@@ -8,6 +8,8 @@ public interface Vertex extends Element {
 
 	public Graph getChildGraph();
 
+	public void removeChildGraph();
+
 	public Iterable<Edge> getEdges(Direction direction);
 
 	public Iterable<Vertex> getVertices(Direction direction);
diff --git a/src/main/java/kieker/analysis/util/graph/export/AbstractTransformer.java b/src/main/java/kieker/analysis/util/graph/export/AbstractTransformer.java
new file mode 100644
index 0000000000000000000000000000000000000000..517512fbf5d66a1afb927067597ac99bc2a9c85c
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/export/AbstractTransformer.java
@@ -0,0 +1,52 @@
+package kieker.analysis.util.graph.export;
+
+import kieker.analysis.util.graph.Edge;
+import kieker.analysis.util.graph.Graph;
+import kieker.analysis.util.graph.Vertex;
+import kieker.analysis.util.graph.traversal.EdgeVisitor;
+import kieker.analysis.util.graph.traversal.FlatGraphTraverser;
+import kieker.analysis.util.graph.traversal.GraphTraverser;
+import kieker.analysis.util.graph.traversal.VertexVisitor;
+
+public abstract class AbstractTransformer<O> implements VertexVisitor, EdgeVisitor {
+
+	private final GraphTraverser graphTraverser = new FlatGraphTraverser(this, this);
+
+	protected Graph graph;
+
+	protected AbstractTransformer(final Graph graph) {
+		this.graph = graph;
+	}
+
+	public final O transform() {
+
+		beforeTransformation();
+
+		graphTraverser.traverse(graph);
+
+		afterTransformation();
+
+		return getTransformation();
+	}
+
+	protected abstract void beforeTransformation();
+
+	protected abstract void afterTransformation();
+
+	protected abstract void transformVertex(Vertex vertex);
+
+	protected abstract void transformEdge(Edge edge);
+
+	protected abstract O getTransformation();
+
+	@Override
+	public void visitVertex(final Vertex vertex) {
+		transformVertex(vertex);
+	}
+
+	@Override
+	public void visitEdge(final Edge edge) {
+		transformEdge(edge);
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/export/blueprints/BlueprintsTransformer.java b/src/main/java/kieker/analysis/util/graph/export/blueprints/BlueprintsTransformer.java
new file mode 100644
index 0000000000000000000000000000000000000000..8ec88461f64ec9cbb48128b6de0419fcd4cfbe05
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/export/blueprints/BlueprintsTransformer.java
@@ -0,0 +1,64 @@
+package kieker.analysis.util.graph.export.blueprints;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.tinkerpop.blueprints.impls.tg.TinkerGraph;
+
+import kieker.analysis.util.graph.Direction;
+import kieker.analysis.util.graph.Edge;
+import kieker.analysis.util.graph.Graph;
+import kieker.analysis.util.graph.Vertex;
+import kieker.analysis.util.graph.export.AbstractTransformer;
+
+public class BlueprintsTransformer extends AbstractTransformer<com.tinkerpop.blueprints.Graph> {
+
+	private final com.tinkerpop.blueprints.Graph transformedGraph = new TinkerGraph();
+	private final Map<Vertex, com.tinkerpop.blueprints.Vertex> mappedVertices = new HashMap<>();
+
+	private static final String LABEL_PROPERTY = "label";
+
+	public BlueprintsTransformer(final Graph graph) {
+		super(graph);
+	}
+
+	@Override
+	protected void transformVertex(final Vertex vertex) {
+		com.tinkerpop.blueprints.Vertex mappedVertex = transformedGraph.addVertex(vertex.getId());
+		mappedVertices.put(vertex, mappedVertex);
+		for (final String propertyKey : vertex.getPropertyKeys()) {
+			mappedVertex.setProperty(propertyKey, vertex.getProperty(propertyKey));
+		}
+
+	}
+
+	@Override
+	protected void transformEdge(final Edge edge) {
+		final com.tinkerpop.blueprints.Vertex mappedInVertex = mappedVertices.get(edge.getVertex(Direction.IN));
+		final com.tinkerpop.blueprints.Vertex mappedOutVertex = mappedVertices.get(edge.getVertex(Direction.OUT));
+		String label = edge.getProperty(LABEL_PROPERTY);
+		if (label == null) {
+			label = "";
+		}
+		com.tinkerpop.blueprints.Edge mappedEdge = transformedGraph.addEdge(edge.getId(), mappedOutVertex, mappedInVertex, label);
+		for (final String propertyKey : edge.getPropertyKeys()) {
+			mappedEdge.setProperty(propertyKey, edge.getProperty(propertyKey));
+		}
+	}
+
+	@Override
+	protected com.tinkerpop.blueprints.Graph getTransformation() {
+		return transformedGraph;
+	}
+
+	@Override
+	protected void beforeTransformation() {
+		// Do nothing
+	}
+
+	@Override
+	protected void afterTransformation() {
+		// Do nothing
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/export/blueprints/BlueprintsTransformerStage.java b/src/main/java/kieker/analysis/util/graph/export/blueprints/BlueprintsTransformerStage.java
new file mode 100644
index 0000000000000000000000000000000000000000..8453de12bb0aa791f195aa4b5acb9ada78f7f6e3
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/export/blueprints/BlueprintsTransformerStage.java
@@ -0,0 +1,15 @@
+package kieker.analysis.util.graph.export.blueprints;
+
+import kieker.analysis.util.graph.Graph;
+
+import teetime.stage.basic.AbstractTransformation;
+
+public class BlueprintsTransformerStage extends AbstractTransformation<Graph, com.tinkerpop.blueprints.Graph> {
+
+	@Override
+	protected void execute(final Graph graph) {
+		BlueprintsTransformer transformer = new BlueprintsTransformer(graph);
+		this.getOutputPort().send(transformer.transform());
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/export/dot/DotElementExporter.java b/src/main/java/kieker/analysis/util/graph/export/dot/DotElementExporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..6aa39df2acf1457c99d8f87881ec922b4b93944c
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/export/dot/DotElementExporter.java
@@ -0,0 +1,97 @@
+package kieker.analysis.util.graph.export.dot;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import kieker.analysis.util.graph.Direction;
+import kieker.analysis.util.graph.Edge;
+import kieker.analysis.util.graph.Graph;
+import kieker.analysis.util.graph.Vertex;
+import kieker.analysis.util.graph.export.AbstractTransformer;
+import kieker.analysis.util.graph.util.dot.DotGraphWriter;
+import kieker.analysis.util.graph.util.dot.attributes.DotClusterAttribute;
+
+class DotElementExporter extends AbstractTransformer<Void> {
+
+	protected final DotGraphWriter dotGraphWriter;
+	protected final DotExportConfiguration configuration;
+
+	protected DotElementExporter(final Graph graph, final DotGraphWriter dotGraphWriter, final DotExportConfiguration configuration) {
+		super(graph);
+		this.dotGraphWriter = dotGraphWriter;
+		this.configuration = configuration;
+	}
+
+	@Override
+	protected void transformVertex(final Vertex vertex) {
+		try {
+			if (vertex.hasChildGraph()) {
+				Graph childGraph = vertex.getChildGraph();
+
+				dotGraphWriter.addClusterStart(vertex.getId().toString());
+
+				for (Entry<DotClusterAttribute, Function<Vertex, String>> attribute : configuration.getClusterAttributes().entrySet()) {
+					dotGraphWriter.addGraphAttribute(attribute.getKey().toString(), attribute.getValue().apply(vertex));
+				}
+
+				DotElementExporter childGraphWriter = new DotElementExporter(childGraph, dotGraphWriter, configuration);
+				childGraphWriter.transform();
+
+				dotGraphWriter.addClusterStop();
+			} else {
+				dotGraphWriter.addNode(vertex.getId().toString(), getAttributes(vertex));
+			}
+		} catch (IOException e) {
+			handleIOException(e);
+		}
+	}
+
+	@Override
+	protected void transformEdge(final Edge edge) {
+		try {
+			final String sourceId = edge.getVertex(Direction.OUT).getId().toString();
+			final String targetId = edge.getVertex(Direction.IN).getId().toString();
+
+			dotGraphWriter.addEdge(sourceId, targetId, getAttributes(edge));
+		} catch (IOException e) {
+			handleIOException(e);
+		}
+
+	}
+
+	protected void handleIOException(final IOException ioException) {
+		throw new IllegalStateException(ioException);
+	}
+
+	protected Map<String, String> getAttributes(final Edge edge) {
+		return configuration.getEdgeAttributes().entrySet().stream().collect(Collectors.toMap(
+				e -> e.getKey().toString(),
+				e -> e.getValue().apply(edge)));
+	}
+
+	protected Map<String, String> getAttributes(final Vertex vertex) {
+		return configuration.getNodeAttributes().entrySet().stream().collect(Collectors.toMap(
+				e -> e.getKey().toString(),
+				e -> e.getValue().apply(vertex)));
+	}
+
+	@Override
+	protected void beforeTransformation() {
+		// Do nothing
+
+	}
+
+	@Override
+	protected void afterTransformation() {
+		// Do nothing
+	}
+
+	@Override
+	protected Void getTransformation() {
+		return null;
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/export/dot/DotExportConfiguration.java b/src/main/java/kieker/analysis/util/graph/export/dot/DotExportConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..3ac597e0efcec35f97bb0bc4d77b50518cd81617
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/export/dot/DotExportConfiguration.java
@@ -0,0 +1,48 @@
+package kieker.analysis.util.graph.export.dot;
+
+import java.util.EnumMap;
+import java.util.Map;
+import java.util.function.Function;
+
+import kieker.analysis.util.graph.Edge;
+import kieker.analysis.util.graph.Graph;
+import kieker.analysis.util.graph.Vertex;
+import kieker.analysis.util.graph.util.dot.attributes.DotClusterAttribute;
+import kieker.analysis.util.graph.util.dot.attributes.DotEdgeAttribute;
+import kieker.analysis.util.graph.util.dot.attributes.DotGraphAttribute;
+import kieker.analysis.util.graph.util.dot.attributes.DotNodeAttribute;
+
+public class DotExportConfiguration {
+
+	final private Map<DotGraphAttribute, Function<Graph, String>> graphAttributes = new EnumMap<>(DotGraphAttribute.class);
+	final private Map<DotNodeAttribute, Function<Graph, String>> defaultNodeAttributes = new EnumMap<>(DotNodeAttribute.class);
+	final private Map<DotEdgeAttribute, Function<Graph, String>> defaultEdgeAttributes = new EnumMap<>(DotEdgeAttribute.class);
+	final private Map<DotNodeAttribute, Function<Vertex, String>> nodeAttributes = new EnumMap<>(DotNodeAttribute.class);
+	final private Map<DotEdgeAttribute, Function<Edge, String>> edgeAttributes = new EnumMap<>(DotEdgeAttribute.class);
+	final private Map<DotClusterAttribute, Function<Vertex, String>> clusterAttributes = new EnumMap<>(DotClusterAttribute.class);
+
+	public Map<DotGraphAttribute, Function<Graph, String>> getGraphAttributes() {
+		return graphAttributes;
+	}
+
+	public Map<DotNodeAttribute, Function<Graph, String>> getDefaultNodeAttributes() {
+		return defaultNodeAttributes;
+	}
+
+	public Map<DotEdgeAttribute, Function<Graph, String>> getDefaultEdgeAttributes() {
+		return defaultEdgeAttributes;
+	}
+
+	public Map<DotNodeAttribute, Function<Vertex, String>> getNodeAttributes() {
+		return nodeAttributes;
+	}
+
+	public Map<DotEdgeAttribute, Function<Edge, String>> getEdgeAttributes() {
+		return edgeAttributes;
+	}
+
+	public Map<DotClusterAttribute, Function<Vertex, String>> getClusterAttributes() {
+		return clusterAttributes;
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/export/dot/DotExporter.java b/src/main/java/kieker/analysis/util/graph/export/dot/DotExporter.java
new file mode 100644
index 0000000000000000000000000000000000000000..60e0e8597e5fdacabedf48c23e1a5ea5060daef8
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/export/dot/DotExporter.java
@@ -0,0 +1,61 @@
+package kieker.analysis.util.graph.export.dot;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.function.Function;
+
+import kieker.analysis.util.graph.Graph;
+import kieker.analysis.util.graph.util.dot.DotGraphWriter;
+import kieker.analysis.util.graph.util.dot.attributes.DotEdgeAttribute;
+import kieker.analysis.util.graph.util.dot.attributes.DotGraphAttribute;
+import kieker.analysis.util.graph.util.dot.attributes.DotNodeAttribute;
+
+public class DotExporter extends DotElementExporter {
+
+	public DotExporter(final Graph graph, final Writer writer) {
+		this(graph, writer, new SimpleDotExportConfiguration());
+	}
+
+	public DotExporter(final Graph graph, final Writer writer, final DotExportConfiguration configuration) {
+		super(graph, new DotGraphWriter(writer), configuration);
+	}
+
+	@Override
+	protected void beforeTransformation() {
+		try {
+			dotGraphWriter.start(graph.getName());
+
+			for (Entry<DotGraphAttribute, Function<Graph, String>> attribute : configuration.getGraphAttributes().entrySet()) {
+				dotGraphWriter.addGraphAttribute(attribute.getKey().toString(), attribute.getValue().apply(graph));
+			}
+
+			Map<String, String> defaultNodeAttributes = new HashMap<>();
+			for (Entry<DotNodeAttribute, Function<Graph, String>> attribute : configuration.getDefaultNodeAttributes().entrySet()) {
+				defaultNodeAttributes.put(attribute.getKey().toString(), attribute.getValue().apply(graph));
+			}
+			dotGraphWriter.addDefaultNodeAttributes(defaultNodeAttributes);
+
+			Map<String, String> defaultEdgeAttributes = new HashMap<>();
+			for (Entry<DotEdgeAttribute, Function<Graph, String>> attribute : configuration.getDefaultEdgeAttributes().entrySet()) {
+				defaultEdgeAttributes.put(attribute.getKey().toString(), attribute.getValue().apply(graph));
+			}
+			dotGraphWriter.addDefaultEdgeAttributes(defaultEdgeAttributes);
+
+		} catch (IOException e) {
+			handleIOException(e);
+		}
+	}
+
+	@Override
+	protected void afterTransformation() {
+		try {
+			dotGraphWriter.finish();
+		} catch (IOException e) {
+			handleIOException(e);
+		}
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/export/dot/DotFileWriterStage.java b/src/main/java/kieker/analysis/util/graph/export/dot/DotFileWriterStage.java
new file mode 100644
index 0000000000000000000000000000000000000000..bc8f6772686cee07ff976d351e057eccd1cbb0e7
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/export/dot/DotFileWriterStage.java
@@ -0,0 +1,27 @@
+package kieker.analysis.util.graph.export.dot;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.function.Function;
+
+import kieker.analysis.util.graph.Graph;
+import kieker.analysis.util.graph.mapping.SimpleFileNameMapper;
+import kieker.analysis.util.graph.util.FileExtension;
+
+public class DotFileWriterStage extends DotWriterStage {
+
+	public DotFileWriterStage(final Function<Graph, String> fileNameMapper) {
+		super(fileNameMapper.andThen(fileName -> {
+			try {
+				return new FileWriter(fileName);
+			} catch (IOException e) {
+				throw new IllegalArgumentException(e);
+			}
+		}));
+	}
+
+	public DotFileWriterStage(final String outputDirectory) {
+		this(new SimpleFileNameMapper(outputDirectory, FileExtension.DOT));
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/export/dot/DotWriterStage.java b/src/main/java/kieker/analysis/util/graph/export/dot/DotWriterStage.java
new file mode 100644
index 0000000000000000000000000000000000000000..fe98b9ba1f98f6d39eb69b35ea2ecbed49bb26fe
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/export/dot/DotWriterStage.java
@@ -0,0 +1,34 @@
+package kieker.analysis.util.graph.export.dot;
+
+import java.io.Writer;
+import java.util.function.Function;
+
+import kieker.analysis.util.graph.Graph;
+
+import teetime.framework.AbstractConsumerStage;
+
+public class DotWriterStage extends AbstractConsumerStage<Graph> {
+
+	protected final Function<Graph, Writer> writerMapper;
+
+	protected final DotExportConfiguration exportConfiguration;
+
+	public DotWriterStage(final Function<Graph, Writer> writerMapper) {
+		super();
+		this.writerMapper = writerMapper;
+		this.exportConfiguration = new SimpleDotExportConfiguration();
+	}
+
+	public DotWriterStage(final Function<Graph, Writer> writerMapper, final DotExportConfiguration exportConfiguration) {
+		super();
+		this.writerMapper = writerMapper;
+		this.exportConfiguration = exportConfiguration;
+	}
+
+	@Override
+	protected final void execute(final Graph graph) {
+		DotExporter dotExporter = new DotExporter(graph, writerMapper.apply(graph), exportConfiguration);
+		dotExporter.transform();
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/export/dot/SimpleDotExportConfiguration.java b/src/main/java/kieker/analysis/util/graph/export/dot/SimpleDotExportConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..1cf23224599fbfe7d8035a33c8e43d95d9f8d6fa
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/export/dot/SimpleDotExportConfiguration.java
@@ -0,0 +1,17 @@
+package kieker.analysis.util.graph.export.dot;
+
+import kieker.analysis.util.graph.Edge;
+import kieker.analysis.util.graph.Vertex;
+import kieker.analysis.util.graph.mapping.DirectPropertyMapper;
+import kieker.analysis.util.graph.util.dot.attributes.DotEdgeAttribute;
+import kieker.analysis.util.graph.util.dot.attributes.DotNodeAttribute;
+
+public class SimpleDotExportConfiguration extends DotExportConfiguration {
+
+	public SimpleDotExportConfiguration() {
+		super();
+		this.getNodeAttributes().put(DotNodeAttribute.LABEL, new DirectPropertyMapper<Vertex>("label"));
+		this.getEdgeAttributes().put(DotEdgeAttribute.LABEL, new DirectPropertyMapper<Edge>("label"));
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/export/graphml/GraphMLFileWriterStage.java b/src/main/java/kieker/analysis/util/graph/export/graphml/GraphMLFileWriterStage.java
new file mode 100644
index 0000000000000000000000000000000000000000..594614b69edd021579930135cd500e70948f172e
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/export/graphml/GraphMLFileWriterStage.java
@@ -0,0 +1,27 @@
+package kieker.analysis.util.graph.export.graphml;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.util.function.Function;
+
+import kieker.analysis.util.graph.Graph;
+import kieker.analysis.util.graph.mapping.SimpleFileNameMapper;
+import kieker.analysis.util.graph.util.FileExtension;
+
+public class GraphMLFileWriterStage extends GraphMLWriterStage {
+
+	public GraphMLFileWriterStage(final Function<Graph, String> fileNameMapper) {
+		super(fileNameMapper.andThen(fileName -> {
+			try {
+				return new FileOutputStream(fileName);
+			} catch (FileNotFoundException e) {
+				throw new IllegalArgumentException(e);
+			}
+		}));
+	}
+
+	public GraphMLFileWriterStage(final String outputDirectory) {
+		this(new SimpleFileNameMapper(outputDirectory, FileExtension.GRAPHML));
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/export/graphml/GraphMLTypeTransformationStage.java b/src/main/java/kieker/analysis/util/graph/export/graphml/GraphMLTypeTransformationStage.java
new file mode 100644
index 0000000000000000000000000000000000000000..bdc0cbfb431736d0fcf4ce139ba55c07ed6fdafd
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/export/graphml/GraphMLTypeTransformationStage.java
@@ -0,0 +1,20 @@
+package kieker.analysis.util.graph.export.graphml;
+
+import org.graphdrawing.graphml.GraphType;
+import org.graphdrawing.graphml.GraphmlType;
+
+import teetime.stage.basic.AbstractTransformation;
+
+public class GraphMLTypeTransformationStage extends AbstractTransformation<GraphType, GraphmlType> {
+
+	@Override
+	protected void execute(final GraphType graphType) {
+
+		final GraphmlType graphmlType = new GraphmlType();
+		graphmlType.getGraphOrData().add(graphType);
+
+		this.getOutputPort().send(graphmlType);
+
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/export/graphml/GraphMLWriterStage.java b/src/main/java/kieker/analysis/util/graph/export/graphml/GraphMLWriterStage.java
new file mode 100644
index 0000000000000000000000000000000000000000..d68e269b01d518cbd13423a46a2dc78e413331a8
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/export/graphml/GraphMLWriterStage.java
@@ -0,0 +1,45 @@
+package kieker.analysis.util.graph.export.graphml;
+
+import java.io.OutputStream;
+import java.util.function.Function;
+
+import org.graphdrawing.graphml.GraphmlType;
+
+import kieker.analysis.util.FunctionStage;
+import kieker.analysis.util.JAXBMarshalStage;
+import kieker.analysis.util.graph.Graph;
+
+import teetime.framework.CompositeStage;
+import teetime.framework.InputPort;
+import teetime.stage.basic.distributor.Distributor;
+import teetime.stage.basic.distributor.strategy.CopyByReferenceStrategy;
+
+public class GraphMLWriterStage extends CompositeStage {
+
+	private final InputPort<Graph> inputPort;
+
+	public GraphMLWriterStage(final Function<Graph, OutputStream> outputStreamMapper) {
+
+		final Distributor<Graph> graphDistributor = new Distributor<>(new CopyByReferenceStrategy());
+		final GraphTypeTransformationStage graphTypeTransformer = new GraphTypeTransformationStage();
+		final GraphMLTypeTransformationStage graphMLTypeTransformer = new GraphMLTypeTransformationStage();
+		final JAXBElementWrapperStage jaxbElementWrapper = new JAXBElementWrapperStage();
+		final JAXBMarshalStage<GraphmlType> jaxbMarshaller = new JAXBMarshalStage<>(GraphmlType.class);
+		final FunctionStage<Graph, OutputStream> outputStreamMapperStage = new FunctionStage<>(outputStreamMapper);
+
+		this.inputPort = graphDistributor.getInputPort();
+
+		super.connectPorts(graphDistributor.getNewOutputPort(), graphTypeTransformer.getInputPort());
+		super.connectPorts(graphTypeTransformer.getOutputPort(), graphMLTypeTransformer.getInputPort());
+		super.connectPorts(graphMLTypeTransformer.getOutputPort(), jaxbElementWrapper.getInputPort());
+		super.connectPorts(jaxbElementWrapper.getOutputPort(), jaxbMarshaller.getInputPort1());
+		super.connectPorts(graphDistributor.getNewOutputPort(), outputStreamMapperStage.getInputPort());
+		super.connectPorts(outputStreamMapperStage.getOutputPort(), jaxbMarshaller.getInputPort2());
+
+	}
+
+	public InputPort<Graph> getInputPort() {
+		return this.inputPort;
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/export/graphml/GraphTypeTransformationStage.java b/src/main/java/kieker/analysis/util/graph/export/graphml/GraphTypeTransformationStage.java
new file mode 100644
index 0000000000000000000000000000000000000000..3298857cc17260f11bbbbbc026d7e7c5e7827c16
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/export/graphml/GraphTypeTransformationStage.java
@@ -0,0 +1,21 @@
+package kieker.analysis.util.graph.export.graphml;
+
+import org.graphdrawing.graphml.GraphType;
+
+import kieker.analysis.util.graph.Graph;
+
+import teetime.stage.basic.AbstractTransformation;
+
+public class GraphTypeTransformationStage extends AbstractTransformation<Graph, GraphType> {
+
+	@Override
+	protected void execute(final Graph graph) {
+
+		final GraphTypeTransformer graphTypeTransformer = new GraphTypeTransformer(graph);
+		final GraphType graphType = graphTypeTransformer.transform();
+
+		this.getOutputPort().send(graphType);
+
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/export/graphml/GraphTypeTransformer.java b/src/main/java/kieker/analysis/util/graph/export/graphml/GraphTypeTransformer.java
new file mode 100644
index 0000000000000000000000000000000000000000..9d346b267c16b9ddc58ca624718058e01a0b375d
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/export/graphml/GraphTypeTransformer.java
@@ -0,0 +1,83 @@
+package kieker.analysis.util.graph.export.graphml;
+
+import java.util.List;
+
+import org.graphdrawing.graphml.DataType;
+import org.graphdrawing.graphml.EdgeType;
+import org.graphdrawing.graphml.GraphEdgedefaultType;
+import org.graphdrawing.graphml.GraphType;
+import org.graphdrawing.graphml.NodeType;
+
+import kieker.analysis.util.graph.Direction;
+import kieker.analysis.util.graph.Edge;
+import kieker.analysis.util.graph.Graph;
+import kieker.analysis.util.graph.Vertex;
+import kieker.analysis.util.graph.export.AbstractTransformer;
+
+public class GraphTypeTransformer extends AbstractTransformer<GraphType> {
+
+	private final GraphType graphType;
+
+	public GraphTypeTransformer(final Graph graph) {
+		super(graph);
+		graphType = new GraphType();
+		graphType.setEdgedefault(GraphEdgedefaultType.DIRECTED);
+		graphType.setId(graph.getName());
+	}
+
+	@Override
+	protected void transformVertex(final Vertex vertex) {
+
+		NodeType nodeType = new NodeType();
+		nodeType.setId(vertex.getId().toString());
+		List<Object> dataOrPort = nodeType.getDataOrPort();
+		for (final String propertyKey : vertex.getPropertyKeys()) {
+			DataType dataType = new DataType();
+			dataType.setKey(propertyKey);
+			dataType.setContent(vertex.getProperty(propertyKey).toString());
+			dataOrPort.add(dataType);
+		}
+
+		if (vertex.hasChildGraph()) {
+			Graph childGraph = vertex.getChildGraph();
+			GraphTypeTransformer graphTypeTransformer = new GraphTypeTransformer(childGraph);
+			GraphType childGraphType = graphTypeTransformer.transform();
+			nodeType.setGraph(childGraphType);
+		}
+
+		graphType.getDataOrNodeOrEdge().add(nodeType);
+	}
+
+	@Override
+	protected void transformEdge(final Edge edge) {
+		EdgeType edgeType = new EdgeType();
+		edgeType.setId(edge.getId().toString());
+		edgeType.setSource(edge.getVertex(Direction.OUT).getId().toString());
+		edgeType.setTarget(edge.getVertex(Direction.IN).getId().toString());
+		List<DataType> data = edgeType.getData();
+		for (final String propertyKey : edge.getPropertyKeys()) {
+			DataType dataType = new DataType();
+			dataType.setKey(propertyKey);
+			dataType.setContent(edge.getProperty(propertyKey).toString());
+			data.add(dataType);
+		}
+
+		graphType.getDataOrNodeOrEdge().add(edgeType);
+	}
+
+	@Override
+	protected GraphType getTransformation() {
+		return graphType;
+	}
+
+	@Override
+	protected void beforeTransformation() {
+		// Do nothing
+	}
+
+	@Override
+	protected void afterTransformation() {
+		// Do nothing
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/export/graphml/JAXBElementWrapperStage.java b/src/main/java/kieker/analysis/util/graph/export/graphml/JAXBElementWrapperStage.java
new file mode 100644
index 0000000000000000000000000000000000000000..0a867bdf7234a32fa022ee3726938bbe50b14c2b
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/export/graphml/JAXBElementWrapperStage.java
@@ -0,0 +1,22 @@
+package kieker.analysis.util.graph.export.graphml;
+
+import javax.xml.bind.JAXBElement;
+
+import org.graphdrawing.graphml.GraphmlType;
+import org.graphdrawing.graphml.ObjectFactory;
+
+import teetime.stage.basic.AbstractTransformation;
+
+public class JAXBElementWrapperStage extends AbstractTransformation<GraphmlType, JAXBElement<GraphmlType>> {
+
+	private final ObjectFactory objectFactory = new ObjectFactory();
+
+	@Override
+	protected void execute(final GraphmlType graphmlType) {
+
+		final JAXBElement<GraphmlType> jaxbElement = objectFactory.createGraphml(graphmlType);
+		this.getOutputPort().send(jaxbElement);
+
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/graph/impl/EdgeImpl.java b/src/main/java/kieker/analysis/util/graph/impl/EdgeImpl.java
similarity index 73%
rename from src/main/java/kieker/analysis/graph/impl/EdgeImpl.java
rename to src/main/java/kieker/analysis/util/graph/impl/EdgeImpl.java
index 6909533ce83b20b2247b23cf5a2030af6555371e..c4428497c892dec6295532108de104fd7ec6e512 100644
--- a/src/main/java/kieker/analysis/graph/impl/EdgeImpl.java
+++ b/src/main/java/kieker/analysis/util/graph/impl/EdgeImpl.java
@@ -1,10 +1,10 @@
-package kieker.analysis.graph.impl;
+package kieker.analysis.util.graph.impl;
 
-import kieker.analysis.graph.Direction;
-import kieker.analysis.graph.Edge;
-import kieker.analysis.graph.Vertex;
+import kieker.analysis.util.graph.Direction;
+import kieker.analysis.util.graph.Edge;
+import kieker.analysis.util.graph.Vertex;
 
-class EdgeImpl extends ElementImpl implements Edge {
+class EdgeImpl extends GraphElementImpl implements Edge {
 
 	private final Vertex outVertex;
 	private final Vertex inVertex;
diff --git a/src/main/java/kieker/analysis/graph/impl/ElementImpl.java b/src/main/java/kieker/analysis/util/graph/impl/ElementImpl.java
similarity index 67%
rename from src/main/java/kieker/analysis/graph/impl/ElementImpl.java
rename to src/main/java/kieker/analysis/util/graph/impl/ElementImpl.java
index f1c2dd91928b5bcfbce4191c07fe44f55cf23f98..393713bcad3bfad4b08d6e4bb3b3996424491473 100644
--- a/src/main/java/kieker/analysis/graph/impl/ElementImpl.java
+++ b/src/main/java/kieker/analysis/util/graph/impl/ElementImpl.java
@@ -1,22 +1,15 @@
-package kieker.analysis.graph.impl;
+package kieker.analysis.util.graph.impl;
 
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 
-import kieker.analysis.graph.Element;
+import kieker.analysis.util.graph.Element;
 
 abstract class ElementImpl implements Element {
 
 	protected Map<String, Object> properties = new HashMap<String, Object>();
-	protected final String id;
-	protected final GraphImpl graph;
-
-	protected ElementImpl(final String id, final GraphImpl graph) {
-		this.graph = graph;
-		this.id = id;
-	}
 
 	@Override
 	@SuppressWarnings("unchecked")
@@ -40,12 +33,4 @@ abstract class ElementImpl implements Element {
 		return (T) this.properties.remove(key);
 	}
 
-	@Override
-	abstract public void remove();
-
-	@Override
-	public Object getId() {
-		return this.id;
-	}
-
 }
diff --git a/src/main/java/kieker/analysis/graph/impl/ExceptionFactory.java b/src/main/java/kieker/analysis/util/graph/impl/ExceptionFactory.java
similarity index 88%
rename from src/main/java/kieker/analysis/graph/impl/ExceptionFactory.java
rename to src/main/java/kieker/analysis/util/graph/impl/ExceptionFactory.java
index f437379e32450c8d33ff89145759c990c175bf33..10c786fb3e5549afc68704f709ad435d8c127eeb 100644
--- a/src/main/java/kieker/analysis/graph/impl/ExceptionFactory.java
+++ b/src/main/java/kieker/analysis/util/graph/impl/ExceptionFactory.java
@@ -1,4 +1,4 @@
-package kieker.analysis.graph.impl;
+package kieker.analysis.util.graph.impl;
 
 /**
  * The ExceptionFactory provides standard exceptions for graphs.
@@ -33,6 +33,10 @@ class ExceptionFactory {
 		return new IllegalStateException("Edge with id does not exist: " + id);
 	}
 
+	public static IllegalStateException verticesAreNotInSameGraph(final Object id1, final Object id2) {
+		return new IllegalStateException("Vertices with ids are not in the same graph: " + id1 + ", " + id2);
+	}
+
 	public static IllegalArgumentException bothIsNotSupported() {
 		return new IllegalArgumentException("A direction of BOTH is not supported");
 	}
diff --git a/src/main/java/kieker/analysis/util/graph/impl/GraphElementImpl.java b/src/main/java/kieker/analysis/util/graph/impl/GraphElementImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..69d508f0a2a0751634f3e4cf525665b81a23b663
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/impl/GraphElementImpl.java
@@ -0,0 +1,24 @@
+package kieker.analysis.util.graph.impl;
+
+import kieker.analysis.util.graph.GraphElement;
+
+abstract class GraphElementImpl extends ElementImpl implements GraphElement {
+
+	protected final String id;
+	protected final GraphImpl graph;
+
+	protected GraphElementImpl(final String id, final GraphImpl graph) {
+		super();
+		this.graph = graph;
+		this.id = id;
+	}
+
+	@Override
+	abstract public void remove();
+
+	@Override
+	public Object getId() {
+		return this.id;
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/graph/impl/GraphImpl.java b/src/main/java/kieker/analysis/util/graph/impl/GraphImpl.java
similarity index 69%
rename from src/main/java/kieker/analysis/graph/impl/GraphImpl.java
rename to src/main/java/kieker/analysis/util/graph/impl/GraphImpl.java
index 2dc03d57017b7180a6c2faa273655e93796c3b9a..d6df8acd73c3a683f628cd3ec28fddfe91da71a9 100644
--- a/src/main/java/kieker/analysis/graph/impl/GraphImpl.java
+++ b/src/main/java/kieker/analysis/util/graph/impl/GraphImpl.java
@@ -1,15 +1,16 @@
-package kieker.analysis.graph.impl;
+package kieker.analysis.util.graph.impl;
 
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Stack;
 
-import kieker.analysis.graph.Direction;
-import kieker.analysis.graph.Edge;
-import kieker.analysis.graph.Graph;
-import kieker.analysis.graph.Vertex;
+import kieker.analysis.util.graph.Direction;
+import kieker.analysis.util.graph.Edge;
+import kieker.analysis.util.graph.Graph;
+import kieker.analysis.util.graph.Vertex;
 
-public class GraphImpl implements Graph {
+public class GraphImpl extends ElementImpl implements Graph {
 
 	protected String name = "G";
 
@@ -18,8 +19,14 @@ public class GraphImpl implements Graph {
 
 	protected Long currentDefaultId = 0l;
 
+	protected VertexImpl parentVertex = null;
+
 	public GraphImpl() {}
 
+	protected GraphImpl(final VertexImpl parentVertex) {
+		this.parentVertex = parentVertex;
+	}
+
 	@Override
 	public Vertex addVertex(final Object id) {
 		String idString = null;
@@ -71,6 +78,28 @@ public class GraphImpl implements Graph {
 
 	@Override
 	public Edge addEdge(final Object id, final Vertex outVertex, final Vertex inVertex) {
+
+		Stack<VertexImpl> outVertexParents = new Stack<>();
+		for (VertexImpl parent = (VertexImpl) outVertex; parent != null; parent = parent.graph.parentVertex) {
+			outVertexParents.push(parent);
+		}
+		Stack<VertexImpl> inVertexParents = new Stack<>();
+		for (VertexImpl parent = (VertexImpl) inVertex; parent != null; parent = parent.graph.parentVertex) {
+			inVertexParents.push(parent);
+		}
+
+		if (outVertexParents.peek().graph != inVertexParents.peek().graph) {
+			throw ExceptionFactory.verticesAreNotInSameGraph(outVertex.getId(), inVertex.getId());
+		}
+
+		GraphImpl firstEqualParent = null;
+		while (!outVertexParents.isEmpty() && !inVertexParents.isEmpty() && outVertexParents.peek().graph == inVertexParents.pop().graph) {
+			firstEqualParent = outVertexParents.pop().graph;
+		}
+		return firstEqualParent.addEdgeChecked(id, outVertex, inVertex);
+	}
+
+	protected Edge addEdgeChecked(final Object id, final Vertex outVertex, final Vertex inVertex) {
 		String idString;
 		if (id == null) {
 			do {
@@ -83,8 +112,6 @@ public class GraphImpl implements Graph {
 			}
 		}
 
-		// TODO Maybe: Check whether both vertices are in the same graph
-
 		final Edge edge = new EdgeImpl(idString, outVertex, inVertex, this);
 		this.edges.put(edge.getId().toString(), edge);
 		((VertexImpl) outVertex).addOutEdge(edge);
diff --git a/src/main/java/kieker/analysis/graph/impl/VertexImpl.java b/src/main/java/kieker/analysis/util/graph/impl/VertexImpl.java
similarity index 84%
rename from src/main/java/kieker/analysis/graph/impl/VertexImpl.java
rename to src/main/java/kieker/analysis/util/graph/impl/VertexImpl.java
index aa3fef03fce59a3b60a40731f563c37fc681f92c..7dd55e0b3587d1a1b5aea15146cd5d06032ebc4f 100644
--- a/src/main/java/kieker/analysis/graph/impl/VertexImpl.java
+++ b/src/main/java/kieker/analysis/util/graph/impl/VertexImpl.java
@@ -1,15 +1,15 @@
-package kieker.analysis.graph.impl;
+package kieker.analysis.util.graph.impl;
 
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
 
-import kieker.analysis.graph.Direction;
-import kieker.analysis.graph.Edge;
-import kieker.analysis.graph.Graph;
-import kieker.analysis.graph.Vertex;
+import kieker.analysis.util.graph.Direction;
+import kieker.analysis.util.graph.Edge;
+import kieker.analysis.util.graph.Graph;
+import kieker.analysis.util.graph.Vertex;
 
-class VertexImpl extends ElementImpl implements Vertex {
+class VertexImpl extends GraphElementImpl implements Vertex {
 
 	protected Map<String, Edge> outEdges = new HashMap<String, Edge>();
 	protected Map<String, Edge> inEdges = new HashMap<String, Edge>();
@@ -21,7 +21,7 @@ class VertexImpl extends ElementImpl implements Vertex {
 
 	@Override
 	public Graph addChildGraph() {
-		this.childGraph = new GraphImpl();
+		this.childGraph = new GraphImpl(this);
 		return getChildGraph();
 	}
 
@@ -35,6 +35,11 @@ class VertexImpl extends ElementImpl implements Vertex {
 		return childGraph;
 	}
 
+	@Override
+	public void removeChildGraph() {
+		childGraph = null;
+	}
+
 	@Override
 	public Iterable<Edge> getEdges(final Direction direction) {
 		if (direction.equals(Direction.OUT)) {
diff --git a/src/main/java/kieker/analysis/util/graph/mapping/DirectPropertyMapper.java b/src/main/java/kieker/analysis/util/graph/mapping/DirectPropertyMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..f05400e81cbfbcd56d27e37b2c19ef589d48cf5b
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/mapping/DirectPropertyMapper.java
@@ -0,0 +1,35 @@
+package kieker.analysis.util.graph.mapping;
+
+import java.util.function.Function;
+
+import kieker.analysis.util.graph.Element;
+
+/**
+ * This function maps a graph element by a passed property key to the
+ * corresponding property value and returns it as string.
+ *
+ * @author Sören Henning
+ *
+ */
+public class DirectPropertyMapper<T extends Element> implements Function<T, String> {
+
+	private String propertyKey;
+
+	public DirectPropertyMapper(final String propertyKey) {
+		this.propertyKey = propertyKey;
+	}
+
+	public String getPropertyKey() {
+		return propertyKey;
+	}
+
+	public void setPropertyKey(final String propertyKey) {
+		this.propertyKey = propertyKey;
+	}
+
+	@Override
+	public String apply(final T element) {
+		return element.getProperty(propertyKey);
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/mapping/SimpleFileNameMapper.java b/src/main/java/kieker/analysis/util/graph/mapping/SimpleFileNameMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..d009c945c4134cd5500b6c3361d8b4d8e003adc3
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/mapping/SimpleFileNameMapper.java
@@ -0,0 +1,30 @@
+package kieker.analysis.util.graph.mapping;
+
+import java.util.function.Function;
+
+import kieker.analysis.util.graph.Graph;
+import kieker.analysis.util.graph.util.FileExtension;
+
+/**
+ * This function maps a graph to a file name with the pattern:
+ * output directory + graph name + file extension
+ *
+ * @author Sören Henning
+ *
+ */
+public class SimpleFileNameMapper implements Function<Graph, String> {
+
+	private final String outputDirectory;
+	private final FileExtension fileExtension;
+
+	public SimpleFileNameMapper(final String outputDirectory, final FileExtension fileExtension) {
+		this.outputDirectory = outputDirectory;
+		this.fileExtension = fileExtension;
+	}
+
+	@Override
+	public String apply(final Graph graph) {
+		return outputDirectory + '/' + graph.getName() + '.' + fileExtension;
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/traversal/DeepGraphTraverser.java b/src/main/java/kieker/analysis/util/graph/traversal/DeepGraphTraverser.java
new file mode 100644
index 0000000000000000000000000000000000000000..f0fb9b08c964c4e56a7164fa7c326f9eb8d4d44f
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/traversal/DeepGraphTraverser.java
@@ -0,0 +1,41 @@
+package kieker.analysis.util.graph.traversal;
+
+import java.util.List;
+
+import kieker.analysis.util.graph.Edge;
+import kieker.analysis.util.graph.Graph;
+import kieker.analysis.util.graph.Vertex;
+
+public class DeepGraphTraverser extends GraphTraverser {
+
+	public DeepGraphTraverser() {
+		super();
+	}
+
+	public DeepGraphTraverser(final List<VertexVisitor> vertexVisitors, final List<EdgeVisitor> edgeVisitors) {
+		super(vertexVisitors, edgeVisitors);
+	}
+
+	public DeepGraphTraverser(final VertexVisitor vertexVisitor, final EdgeVisitor edgeVisitor) {
+		super(vertexVisitor, edgeVisitor);
+	}
+
+	@Override
+	public void traverse(final Graph graph) {
+		for (final Vertex vertex : graph.getVertices()) {
+			for (final VertexVisitor visitor : vertexVisitors) {
+				visitor.visitVertex(vertex);
+			}
+			if (vertex.hasChildGraph()) {
+				traverse(vertex.getChildGraph());
+			}
+		}
+
+		for (final Edge edge : graph.getEdges()) {
+			for (final EdgeVisitor visitor : edgeVisitors) {
+				visitor.visitEdge(edge);
+			}
+		}
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/traversal/EdgeVisitor.java b/src/main/java/kieker/analysis/util/graph/traversal/EdgeVisitor.java
new file mode 100644
index 0000000000000000000000000000000000000000..3653d99b5df64224e3fc80274859a8462ba6d285
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/traversal/EdgeVisitor.java
@@ -0,0 +1,9 @@
+package kieker.analysis.util.graph.traversal;
+
+import kieker.analysis.util.graph.Edge;
+
+public interface EdgeVisitor {
+
+	public void visitEdge(Edge edge);
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/traversal/FlatGraphTraverser.java b/src/main/java/kieker/analysis/util/graph/traversal/FlatGraphTraverser.java
new file mode 100644
index 0000000000000000000000000000000000000000..fff34cf8a23d06552903c1ba62404223852b2835
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/traversal/FlatGraphTraverser.java
@@ -0,0 +1,40 @@
+package kieker.analysis.util.graph.traversal;
+
+import java.util.List;
+
+import kieker.analysis.util.graph.Edge;
+import kieker.analysis.util.graph.Graph;
+import kieker.analysis.util.graph.Vertex;
+
+public class FlatGraphTraverser extends GraphTraverser {
+
+	public FlatGraphTraverser() {
+		super();
+	}
+
+	public FlatGraphTraverser(final List<VertexVisitor> vertexVisitors, final List<EdgeVisitor> edgeVisitors) {
+		super(vertexVisitors, edgeVisitors);
+	}
+
+	public FlatGraphTraverser(final VertexVisitor vertexVisitor, final EdgeVisitor edgeVisitor) {
+		super(vertexVisitor, edgeVisitor);
+	}
+
+	@Override
+	public void traverse(final Graph graph) {
+
+		for (Vertex vertex : graph.getVertices()) {
+			for (VertexVisitor visitor : vertexVisitors) {
+				visitor.visitVertex(vertex);
+			}
+		}
+
+		for (Edge edge : graph.getEdges()) {
+			for (EdgeVisitor visitor : edgeVisitors) {
+				visitor.visitEdge(edge);
+			}
+		}
+
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/traversal/GraphTraverser.java b/src/main/java/kieker/analysis/util/graph/traversal/GraphTraverser.java
new file mode 100644
index 0000000000000000000000000000000000000000..051eed244aedcca2beaab290e0a38d2143dafbfe
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/traversal/GraphTraverser.java
@@ -0,0 +1,55 @@
+package kieker.analysis.util.graph.traversal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import kieker.analysis.util.graph.Graph;
+
+public abstract class GraphTraverser {
+
+	protected List<VertexVisitor> vertexVisitors;
+	protected List<EdgeVisitor> edgeVisitors;
+
+	public GraphTraverser() {
+		this.vertexVisitors = new ArrayList<>();
+		this.edgeVisitors = new ArrayList<>();
+	}
+
+	public GraphTraverser(final VertexVisitor vertexVisitor, final EdgeVisitor edgeVisitor) {
+		this();
+		vertexVisitors.add(vertexVisitor);
+		edgeVisitors.add(edgeVisitor);
+	}
+
+	public GraphTraverser(final List<VertexVisitor> vertexVisitors, final List<EdgeVisitor> edgeVisitors) {
+		this.vertexVisitors = vertexVisitors;
+		this.edgeVisitors = edgeVisitors;
+	}
+
+	public List<VertexVisitor> getVertexVisitors() {
+		return vertexVisitors;
+	}
+
+	public void setVertexVisitors(final List<VertexVisitor> vertexVisitors) {
+		this.vertexVisitors = vertexVisitors;
+	}
+
+	public void addVertexVisitor(final VertexVisitor vertexVisitor) {
+		vertexVisitors.add(vertexVisitor);
+	}
+
+	public List<EdgeVisitor> getEdgeVisitors() {
+		return edgeVisitors;
+	}
+
+	public void setEdgeVisitors(final List<EdgeVisitor> edgeVisitors) {
+		this.edgeVisitors = edgeVisitors;
+	}
+
+	public void addEdgeVisitor(final EdgeVisitor edgeVisitor) {
+		edgeVisitors.add(edgeVisitor);
+	}
+
+	public abstract void traverse(final Graph graph);
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/traversal/VertexVisitor.java b/src/main/java/kieker/analysis/util/graph/traversal/VertexVisitor.java
new file mode 100644
index 0000000000000000000000000000000000000000..cfdcbe3e49e5cfb6a38fff8ea47851de28596e7b
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/traversal/VertexVisitor.java
@@ -0,0 +1,9 @@
+package kieker.analysis.util.graph.traversal;
+
+import kieker.analysis.util.graph.Vertex;
+
+public interface VertexVisitor {
+
+	public void visitVertex(Vertex vertex);
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/util/FileExtension.java b/src/main/java/kieker/analysis/util/graph/util/FileExtension.java
new file mode 100644
index 0000000000000000000000000000000000000000..ef27b1dafafa0dd07e866c504e1bbdcc31f68e02
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/util/FileExtension.java
@@ -0,0 +1,18 @@
+package kieker.analysis.util.graph.util;
+
+public enum FileExtension {
+
+	GRAPHML("graphml"), DOT("dot");
+
+	private final String fileExtension;
+
+	private FileExtension(final String fileExtension) {
+		this.fileExtension = fileExtension;
+	}
+
+	@Override
+	public String toString() {
+		return this.fileExtension;
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/util/IndentWriter.java b/src/main/java/kieker/analysis/util/graph/util/IndentWriter.java
new file mode 100644
index 0000000000000000000000000000000000000000..e5604512d95e8560aac0dae01320bfdd0d3f3ba6
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/util/IndentWriter.java
@@ -0,0 +1,61 @@
+package kieker.analysis.util.graph.util;
+
+import java.io.IOException;
+import java.io.Writer;
+
+public class IndentWriter extends Writer {
+
+	private final Writer writer;
+
+	private int indented = 0;
+	private char indentChar = DEFAULT_INDENT_CHAR;
+	private int indentLength = DEFAULT_INDENT_LENGTH;
+
+	public static final char DEFAULT_INDENT_CHAR = '\t';
+	public static final int DEFAULT_INDENT_LENGTH = 1;
+
+	public IndentWriter(final Writer writer) {
+		super();
+		this.writer = writer;
+	}
+
+	public IndentWriter(final Writer writer, final char indentChar, final int indentLength) {
+		this(writer);
+		this.indentChar = indentChar;
+		this.indentLength = indentLength;
+	}
+
+	public void indent() {
+		indented++;
+	}
+
+	public void unindent() {
+		if (indented > 0) {
+			indented--;
+		}
+	}
+
+	public void writeln(final String str) throws IOException {
+		writer.write(getIndentChars() + str + '\n');
+	}
+
+	private String getIndentChars() {
+		return new String(new char[indented * indentLength]).replace('\0', indentChar);
+	}
+
+	@Override
+	public void write(final char[] cbuf, final int off, final int len) throws IOException {
+		writer.write(cbuf, off, len);
+	}
+
+	@Override
+	public void flush() throws IOException {
+		writer.flush();
+	}
+
+	@Override
+	public void close() throws IOException {
+		writer.close();
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/util/dot/DotGraph.java b/src/main/java/kieker/analysis/util/graph/util/dot/DotGraph.java
new file mode 100644
index 0000000000000000000000000000000000000000..d95cf11d6fff28f35826ffae181f77fb35a8fc18
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/util/dot/DotGraph.java
@@ -0,0 +1,31 @@
+package kieker.analysis.util.graph.util.dot;
+
+public final class DotGraph {
+
+	public static final String START_GRAPH_BRACKET = "{";
+
+	public static final String END_GRAPH_BRACKET = "}";
+
+	public static final String START_ATTRS_BRACKET = "[";
+
+	public static final String END_ATTRS_BRACKET = "]";
+
+	public static final String ATTR_CONNECTOR = "=";
+
+	public static final String DIRECTED_START_TOKEN = "digraph";
+
+	public static final String UNDIRECTED_START_TOKEN = "graph";
+
+	public static final String SUB_START_TOKEN = "subgraph";
+
+	public static final String NODE = "node";
+
+	public static final String EDGE = "edge";
+
+	public static final String CLUSTER_PREFIX = "cluster_";
+
+	public static final String DIRECTED_EDGE_CONNECTOR = "->";
+
+	public static final String UNDIRECTED_EDGE_CONNECTOR = "--";
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/util/dot/DotGraphType.java b/src/main/java/kieker/analysis/util/graph/util/dot/DotGraphType.java
new file mode 100644
index 0000000000000000000000000000000000000000..49cba4710f0d93656ccd9c50efe93c6af5e8d3eb
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/util/dot/DotGraphType.java
@@ -0,0 +1,7 @@
+package kieker.analysis.util.graph.util.dot;
+
+public enum DotGraphType {
+
+	DIRECTED, UNDIRECTED
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/util/dot/DotGraphWriter.java b/src/main/java/kieker/analysis/util/graph/util/dot/DotGraphWriter.java
new file mode 100644
index 0000000000000000000000000000000000000000..e895fb3d6f15c9d7c2a93e2eae1babd9712a0eec
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/util/dot/DotGraphWriter.java
@@ -0,0 +1,178 @@
+package kieker.analysis.util.graph.util.dot;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import kieker.analysis.util.graph.util.IndentWriter;
+
+/**
+ * Class to build and write a DOT Graph to a writer.
+ *
+ * @author Sören Henning
+ *
+ */
+public class DotGraphWriter {
+
+	private final IndentWriter writer;
+	private DotWriterState state = DotWriterState.CREATED;
+	private int openSubgraphs = 0;
+
+	private DotGraphType graphType = DotGraphType.DIRECTED;
+
+	public DotGraphWriter(final Writer writer) {
+		this.writer = new IndentWriter(writer);
+	}
+
+	public void start(final String name) throws IOException {
+		start(DotGraphType.DIRECTED, name);
+	}
+
+	public void start(final DotGraphType graphType, final String name) throws IOException {
+		checkState(DotWriterState.CREATED);
+
+		this.graphType = graphType;
+
+		String openToken;
+		if (graphType == DotGraphType.UNDIRECTED) {
+			openToken = DotGraph.UNDIRECTED_START_TOKEN;
+		} else {
+			openToken = DotGraph.DIRECTED_START_TOKEN;
+		}
+		writer.writeln(openToken + ' ' + '"' + name + '"' + ' ' + DotGraph.START_GRAPH_BRACKET);
+		writer.indent();
+		state = DotWriterState.STARTED;
+	}
+
+	public void finish() throws IOException {
+		checkState(DotWriterState.STARTED);
+
+		if (openSubgraphs > 0) {
+			throw new IllegalStateException("There are unclosed subgraphs.");
+		}
+
+		writer.unindent();
+		writer.writeln(DotGraph.END_GRAPH_BRACKET);
+		state = DotWriterState.FINISHED;
+
+		writer.close();
+	}
+
+	public void addDefaultNodeAttributes(final Map<String, String> attributes) throws IOException {
+		checkState(DotWriterState.STARTED);
+
+		if (attributes != null && !attributes.isEmpty()) {
+			writer.writeln(DotGraph.NODE + ' ' + assembleAttributes(attributes));
+		}
+	}
+
+	public void addDefaultEdgeAttributes(final Map<String, String> attributes) throws IOException {
+		checkState(DotWriterState.STARTED);
+
+		if (attributes != null && !attributes.isEmpty()) {
+			writer.writeln(DotGraph.EDGE + ' ' + assembleAttributes(attributes));
+		}
+	}
+
+	public void addGraphAttribute(final String key, final String value) throws IOException {
+		checkState(DotWriterState.STARTED);
+
+		writer.writeln(assembleAttribute(key, value));
+	}
+
+	public void addNode(final String id) throws IOException {
+		addNode(id, null);
+	}
+
+	public void addNode(final String id, final Map<String, String> attributes) throws IOException {
+		checkState(DotWriterState.STARTED);
+
+		if (attributes == null || attributes.isEmpty()) {
+			writer.writeln('"' + id + '"');
+		} else {
+			writer.writeln('"' + id + '"' + ' ' + assembleAttributes(attributes));
+		}
+	}
+
+	public void addEdge(final String sourceId, final String targetId) throws IOException {
+		addEdge(sourceId, targetId, null);
+	}
+
+	public void addEdge(final String sourceId, final String targetId, final Map<String, String> attributes) throws IOException {
+		checkState(DotWriterState.STARTED);
+
+		String edgeConnector;
+		if (graphType == DotGraphType.UNDIRECTED) {
+			edgeConnector = DotGraph.UNDIRECTED_EDGE_CONNECTOR;
+		} else {
+			edgeConnector = DotGraph.DIRECTED_EDGE_CONNECTOR;
+		}
+
+		if (attributes == null || attributes.isEmpty()) {
+			writer.writeln('"' + sourceId + '"' + ' ' + edgeConnector + ' ' + '"' + targetId + '"');
+		} else {
+			writer.writeln('"' + sourceId + '"' + ' ' + edgeConnector + ' ' + '"' + targetId + '"' + ' ' + assembleAttributes(attributes));
+		}
+	}
+
+	public void addSubgraphStart(final String name) throws IOException {
+		checkState(DotWriterState.STARTED);
+
+		writer.writeln(DotGraph.SUB_START_TOKEN + ' ' + '"' + name + '"' + ' ' + DotGraph.START_GRAPH_BRACKET);
+		writer.indent();
+		openSubgraphs++;
+	}
+
+	public void addSubgraphStop() throws IOException {
+		checkState(DotWriterState.STARTED);
+
+		if (openSubgraphs == 0) {
+			throw new IllegalStateException("There is no subgraph to close.");
+		}
+
+		writer.unindent();
+		writer.writeln(DotGraph.END_GRAPH_BRACKET);
+		openSubgraphs--;
+	}
+
+	public void addClusterStart(final String name) throws IOException {
+		addSubgraphStart(DotGraph.CLUSTER_PREFIX + name);
+	}
+
+	public void addClusterStop() throws IOException {
+		addSubgraphStop();
+	}
+
+	private void checkState(final DotWriterState expectedState) {
+		if (state != expectedState) {
+			switch (expectedState) {
+			case CREATED:
+				throw new IllegalStateException("The writing has already been started.");
+			case STARTED:
+				throw new IllegalStateException("The writing has never started or already been finished.");
+			case FINISHED:
+				throw new IllegalStateException("The writing has not been finished.");
+			default:
+				throw new IllegalStateException();
+			}
+		}
+	}
+
+	private String assembleAttributes(final Map<String, String> attributes) {
+		return DotGraph.START_ATTRS_BRACKET
+				+ attributes.entrySet().stream()
+						.map(e -> assembleAttribute(e.getKey(), e.getValue()))
+						.collect(Collectors.joining(","))
+				+ DotGraph.END_ATTRS_BRACKET;
+	}
+
+	private String assembleAttribute(final String key, final String value) {
+		return key + DotGraph.ATTR_CONNECTOR + '"' + value + '"';
+	}
+
+	private enum DotWriterState {
+		CREATED, STARTED, FINISHED
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/util/dot/attributes/DotClusterAttribute.java b/src/main/java/kieker/analysis/util/graph/util/dot/attributes/DotClusterAttribute.java
new file mode 100644
index 0000000000000000000000000000000000000000..33a2d4234f316e88e6310450d622eeefa5292cfe
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/util/dot/attributes/DotClusterAttribute.java
@@ -0,0 +1,18 @@
+package kieker.analysis.util.graph.util.dot.attributes;
+
+public enum DotClusterAttribute {
+
+	LABEL("label");
+
+	private final String attribute;
+
+	private DotClusterAttribute(final String attribute) {
+		this.attribute = attribute;
+	}
+
+	@Override
+	public String toString() {
+		return this.attribute;
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/util/dot/attributes/DotEdgeAttribute.java b/src/main/java/kieker/analysis/util/graph/util/dot/attributes/DotEdgeAttribute.java
new file mode 100644
index 0000000000000000000000000000000000000000..8239a255199ca8cb3c231a9c3365543d5dfdb894
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/util/dot/attributes/DotEdgeAttribute.java
@@ -0,0 +1,18 @@
+package kieker.analysis.util.graph.util.dot.attributes;
+
+public enum DotEdgeAttribute {
+
+	LABEL("label"), ARROWHEAD("arrowhead"), ARROWSIZE("arrowsize"), ARROWTAIL("arrowtail");
+
+	private final String attribute;
+
+	private DotEdgeAttribute(final String attribute) {
+		this.attribute = attribute;
+	}
+
+	@Override
+	public String toString() {
+		return this.attribute;
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/util/dot/attributes/DotGraphAttribute.java b/src/main/java/kieker/analysis/util/graph/util/dot/attributes/DotGraphAttribute.java
new file mode 100644
index 0000000000000000000000000000000000000000..71e42068357b11bc79bde913abb6374136b0a8f0
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/util/dot/attributes/DotGraphAttribute.java
@@ -0,0 +1,18 @@
+package kieker.analysis.util.graph.util.dot.attributes;
+
+public enum DotGraphAttribute {
+
+	LABEL("label"), RANKDIR("rankdir");
+
+	private final String attribute;
+
+	private DotGraphAttribute(final String attribute) {
+		this.attribute = attribute;
+	}
+
+	@Override
+	public String toString() {
+		return this.attribute;
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/util/dot/attributes/DotNodeAttribute.java b/src/main/java/kieker/analysis/util/graph/util/dot/attributes/DotNodeAttribute.java
new file mode 100644
index 0000000000000000000000000000000000000000..242f8637523c27a326f12feb39b90a6341460535
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/util/dot/attributes/DotNodeAttribute.java
@@ -0,0 +1,18 @@
+package kieker.analysis.util.graph.util.dot.attributes;
+
+public enum DotNodeAttribute {
+
+	LABEL("label"), SHAPE("shape");
+
+	private final String attribute;
+
+	private DotNodeAttribute(final String attribute) {
+		this.attribute = attribute;
+	}
+
+	@Override
+	public String toString() {
+		return this.attribute;
+	}
+
+}
diff --git a/src/main/java/kieker/analysis/util/graph/util/dot/attributes/DotSubgraphAttribute.java b/src/main/java/kieker/analysis/util/graph/util/dot/attributes/DotSubgraphAttribute.java
new file mode 100644
index 0000000000000000000000000000000000000000..a674652e8ea6f4f6f948cf5ea0ced976ffccd860
--- /dev/null
+++ b/src/main/java/kieker/analysis/util/graph/util/dot/attributes/DotSubgraphAttribute.java
@@ -0,0 +1,18 @@
+package kieker.analysis.util.graph.util.dot.attributes;
+
+public enum DotSubgraphAttribute {
+
+	;
+
+	private final String attribute;
+
+	private DotSubgraphAttribute(final String attribute) {
+		this.attribute = attribute;
+	}
+
+	@Override
+	public String toString() {
+		return this.attribute;
+	}
+
+}