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; + } + +}