Skip to content

Commit

Permalink
Merge pull request jgrapht#288 from d-michail/ext-providers-interface…
Browse files Browse the repository at this point in the history
…-refactoring

Unified name providers for exporters using a common interface
  • Loading branch information
jsichi authored Sep 20, 2016
2 parents d031a31 + c188db8 commit 30dade5
Show file tree
Hide file tree
Showing 24 changed files with 469 additions and 186 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -165,14 +165,14 @@ public GraphVertex createVertex()

// create GraphML exporter
GraphMLExporter<GraphVertex, DefaultWeightedEdge> exporter =
new GraphMLExporter<>(new VertexNameProvider<GraphVertex>()
new GraphMLExporter<>(new ComponentNameProvider<GraphVertex>()
{
@Override
public String getVertexName(GraphVertex v)
public String getName(GraphVertex v)
{
return v.id;
}
}, null, new IntegerEdgeNameProvider<>(), null);
}, null, new IntegerComponentNameProvider<>(), null);

// set to export the internal edge weights
exporter.setExportEdgeWeights(true);
Expand Down
26 changes: 13 additions & 13 deletions jgrapht-ext/src/main/java/org/jgrapht/ext/CSVExporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public class CSVExporter<V, E>
{
private static final char DEFAULT_DELIMITER = ',';

private final VertexNameProvider<V> vertexIDProvider;
private final ComponentNameProvider<V> vertexIDProvider;
private final Set<CSVFormat.Parameter> parameters;
private CSVFormat format;
private char delimiter;
Expand All @@ -66,7 +66,7 @@ public class CSVExporter<V, E>
*/
public CSVExporter()
{
this(new IntegerNameProvider<>(), CSVFormat.ADJACENCY_LIST, DEFAULT_DELIMITER);
this(new IntegerComponentNameProvider<>(), CSVFormat.ADJACENCY_LIST, DEFAULT_DELIMITER);
}

/**
Expand All @@ -76,7 +76,7 @@ public CSVExporter()
*/
public CSVExporter(CSVFormat format)
{
this(new IntegerNameProvider<>(), format, DEFAULT_DELIMITER);
this(new IntegerComponentNameProvider<>(), format, DEFAULT_DELIMITER);
}

/**
Expand All @@ -87,7 +87,7 @@ public CSVExporter(CSVFormat format)
*/
public CSVExporter(CSVFormat format, char delimiter)
{
this(new IntegerNameProvider<>(), format, delimiter);
this(new IntegerComponentNameProvider<>(), format, delimiter);
}

/**
Expand All @@ -97,7 +97,7 @@ public CSVExporter(CSVFormat format, char delimiter)
* @param format the format to use
* @param delimiter delimiter to use
*/
public CSVExporter(VertexNameProvider<V> vertexIDProvider, CSVFormat format, char delimiter)
public CSVExporter(ComponentNameProvider<V> vertexIDProvider, CSVFormat format, char delimiter)
{
if (vertexIDProvider == null) {
throw new IllegalArgumentException("Vertex id provider cannot be null");
Expand Down Expand Up @@ -207,9 +207,9 @@ public void setDelimiter(char delimiter)
private void exportAsEdgeList(Graph<V, E> g, PrintWriter out)
{
for (E e : g.edgeSet()) {
exportEscapedField(out, vertexIDProvider.getVertexName(g.getEdgeSource(e)));
exportEscapedField(out, vertexIDProvider.getName(g.getEdgeSource(e)));
out.print(delimiter);
exportEscapedField(out, vertexIDProvider.getVertexName(g.getEdgeTarget(e)));
exportEscapedField(out, vertexIDProvider.getName(g.getEdgeTarget(e)));
out.println();
}
}
Expand All @@ -218,21 +218,21 @@ private void exportAsAdjacencyList(Graph<V, E> g, PrintWriter out)
{
if (g instanceof DirectedGraph<?, ?>) {
for (V v : g.vertexSet()) {
exportEscapedField(out, vertexIDProvider.getVertexName(v));
exportEscapedField(out, vertexIDProvider.getName(v));
for (E e : ((DirectedGraph<V, E>) g).outgoingEdgesOf(v)) {
V w = Graphs.getOppositeVertex(g, e, v);
out.print(delimiter);
exportEscapedField(out, vertexIDProvider.getVertexName(w));
exportEscapedField(out, vertexIDProvider.getName(w));
}
out.println();
}
} else {
for (V v : g.vertexSet()) {
exportEscapedField(out, vertexIDProvider.getVertexName(v));
exportEscapedField(out, vertexIDProvider.getName(v));
for (E e : g.edgesOf(v)) {
V w = Graphs.getOppositeVertex(g, e, v);
out.print(delimiter);
exportEscapedField(out, vertexIDProvider.getVertexName(w));
exportEscapedField(out, vertexIDProvider.getName(w));
}
out.println();
}
Expand All @@ -250,14 +250,14 @@ private void exportAsMatrix(Graph<V, E> g, PrintWriter out)
if (exportNodeId) {
for (V v : g.vertexSet()) {
out.print(delimiter);
exportEscapedField(out, vertexIDProvider.getVertexName(v));
exportEscapedField(out, vertexIDProvider.getName(v));
}
out.println();
}
int n = g.vertexSet().size();
for (V v : g.vertexSet()) {
if (exportNodeId) {
exportEscapedField(out, vertexIDProvider.getVertexName(v));
exportEscapedField(out, vertexIDProvider.getName(v));
out.print(delimiter);
}
int i = 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* (C) Copyright 2016-2016, by Dimitrios Michail and Contributors.
*
* JGraphT : a free Java graph-theory library
*
* This program and the accompanying materials are dual-licensed under
* either
*
* (a) the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation, or (at your option) any
* later version.
*
* or (per the licensee's choosing)
*
* (b) the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation.
*/
package org.jgrapht.ext;

/**
* Provides a name for a component.
*
* @param <T> the type of the component
*/
public interface ComponentNameProvider<T>
{

/**
* Returns a unique name. This is useful when exporting a graph, as it ensures that all
* vertices/edges are assigned simple, consistent names.
*
* @param component the component to be named
* @return the name of the component
*/
String getName(T component);

}

// End ComponentNameProvider.java
39 changes: 39 additions & 0 deletions jgrapht-ext/src/main/java/org/jgrapht/ext/ComponentUpdater.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* (C) Copyright 2015-2016, by Wil Selwood and Contributors.
*
* JGraphT : a free Java graph-theory library
*
* This program and the accompanying materials are dual-licensed under
* either
*
* (a) the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation, or (at your option) any
* later version.
*
* or (per the licensee's choosing)
*
* (b) the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation.
*/
package org.jgrapht.ext;

import java.util.*;

/**
* Type to handle updates to a component when an import gets more information about it after it has
* been created.
*
* @param <T> the component type
*/
public interface ComponentUpdater<T>
{
/**
* Update component with the extra attributes.
*
* @param component to update
* @param attributes to add to the component
*/
void update(T component, Map<String, String> attributes);
}

// End ComponentUpdater.java
72 changes: 58 additions & 14 deletions jgrapht-ext/src/main/java/org/jgrapht/ext/DOTExporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,15 @@
public class DOTExporter<V, E>
implements GraphExporter<V, E>
{
private VertexNameProvider<V> vertexIDProvider;
private VertexNameProvider<V> vertexLabelProvider;
private EdgeNameProvider<E> edgeLabelProvider;
/**
* Default graph id used by the exporter.
*/
public static final String DEFAULT_GRAPH_ID = "G";

private ComponentNameProvider<Graph<V, E>> graphIDProvider;
private ComponentNameProvider<V> vertexIDProvider;
private ComponentNameProvider<V> vertexLabelProvider;
private ComponentNameProvider<E> edgeLabelProvider;
private ComponentAttributeProvider<V> vertexAttributeProvider;
private ComponentAttributeProvider<E> edgeAttributeProvider;

Expand All @@ -50,7 +56,7 @@ public class DOTExporter<V, E>
*/
public DOTExporter()
{
this(new IntegerNameProvider<>(), null, null);
this(new IntegerComponentNameProvider<>(), null, null, null, null, null);
}

/**
Expand All @@ -63,10 +69,10 @@ public DOTExporter()
* to the file.
*/
public DOTExporter(
VertexNameProvider<V> vertexIDProvider, VertexNameProvider<V> vertexLabelProvider,
EdgeNameProvider<E> edgeLabelProvider)
ComponentNameProvider<V> vertexIDProvider, ComponentNameProvider<V> vertexLabelProvider,
ComponentNameProvider<E> edgeLabelProvider)
{
this(vertexIDProvider, vertexLabelProvider, edgeLabelProvider, null, null);
this(vertexIDProvider, vertexLabelProvider, edgeLabelProvider, null, null, null);
}

/**
Expand All @@ -86,16 +92,48 @@ public DOTExporter(
* not be written to the file.
*/
public DOTExporter(
VertexNameProvider<V> vertexIDProvider, VertexNameProvider<V> vertexLabelProvider,
EdgeNameProvider<E> edgeLabelProvider,
ComponentNameProvider<V> vertexIDProvider, ComponentNameProvider<V> vertexLabelProvider,
ComponentNameProvider<E> edgeLabelProvider,
ComponentAttributeProvider<V> vertexAttributeProvider,
ComponentAttributeProvider<E> edgeAttributeProvider)
{
this(
vertexIDProvider, vertexLabelProvider, edgeLabelProvider, vertexAttributeProvider,
edgeAttributeProvider, null);
}

/**
* Constructs a new DOTExporter object with the given ID, label, attribute, and graph id
* providers. Note that if a label provider conflicts with a label-supplying attribute provider,
* the label provider is given precedence.
*
* @param vertexIDProvider for generating vertex IDs. Must not be null.
* @param vertexLabelProvider for generating vertex labels. If null, vertex labels will not be
* written to the file (unless an attribute provider is supplied which also supplies
* labels).
* @param edgeLabelProvider for generating edge labels. If null, edge labels will not be written
* to the file.
* @param vertexAttributeProvider for generating vertex attributes. If null, vertex attributes
* will not be written to the file.
* @param edgeAttributeProvider for generating edge attributes. If null, edge attributes will
* not be written to the file.
* @param graphIDProvider for generating the graph ID. If null the graph is named
* {@link #DEFAULT_GRAPH_ID}.
*/
public DOTExporter(
ComponentNameProvider<V> vertexIDProvider, ComponentNameProvider<V> vertexLabelProvider,
ComponentNameProvider<E> edgeLabelProvider,
ComponentAttributeProvider<V> vertexAttributeProvider,
ComponentAttributeProvider<E> edgeAttributeProvider,
ComponentNameProvider<Graph<V, E>> graphIDProvider)
{
this.vertexIDProvider = vertexIDProvider;
this.vertexLabelProvider = vertexLabelProvider;
this.edgeLabelProvider = edgeLabelProvider;
this.vertexAttributeProvider = vertexAttributeProvider;
this.edgeAttributeProvider = edgeAttributeProvider;
this.graphIDProvider =
(graphIDProvider == null) ? any -> DEFAULT_GRAPH_ID : graphIDProvider;
}

/**
Expand All @@ -111,11 +149,16 @@ public void exportGraph(Graph<V, E> g, Writer writer)
String indent = " ";
String connector;

String graphId = graphIDProvider.getName(g);
if (graphId == null || graphId.trim().isEmpty()) {
graphId = DEFAULT_GRAPH_ID;
}

if (g instanceof DirectedGraph<?, ?>) {
out.println("digraph G {");
out.println("digraph " + graphId + " {");
connector = " -> ";
} else {
out.println("graph G {");
out.println("graph " + graphId + " {");
connector = " -- ";
}

Expand All @@ -124,7 +167,7 @@ public void exportGraph(Graph<V, E> g, Writer writer)

String labelName = null;
if (vertexLabelProvider != null) {
labelName = vertexLabelProvider.getVertexName(v);
labelName = vertexLabelProvider.getName(v);
}
Map<String, String> attributes = null;
if (vertexAttributeProvider != null) {
Expand All @@ -143,7 +186,7 @@ public void exportGraph(Graph<V, E> g, Writer writer)

String labelName = null;
if (edgeLabelProvider != null) {
labelName = edgeLabelProvider.getEdgeName(e);
labelName = edgeLabelProvider.getName(e);
}
Map<String, String> attributes = null;
if (edgeAttributeProvider != null) {
Expand Down Expand Up @@ -206,7 +249,7 @@ private String getVertexID(V v)
// (b) compile regex patterns

// use the associated id provider for an ID of the given vertex
String idCandidate = vertexIDProvider.getVertexName(v);
String idCandidate = vertexIDProvider.getName(v);

// now test that this is a valid ID
boolean isAlphaDig = idCandidate.matches("[a-zA-Z]+([\\w_]*)?");
Expand All @@ -222,6 +265,7 @@ private String getVertexID(V v)
"Generated id '" + idCandidate + "'for vertex '" + v
+ "' is not valid with respect to the .dot language");
}

}

// End DOTExporter.java
10 changes: 5 additions & 5 deletions jgrapht-ext/src/main/java/org/jgrapht/ext/DOTImporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public class DOTImporter<V, E>
private static final int DONE = 32;

private VertexProvider<V> vertexProvider;
private VertexUpdater<V> vertexUpdater;
private ComponentUpdater<V> vertexUpdater;
private EdgeProvider<V, E> edgeProvider;

/**
Expand All @@ -123,13 +123,13 @@ public DOTImporter(VertexProvider<V> vertexProvider, EdgeProvider<V, E> edgeProv
*
* @param vertexProvider Provider to create a vertex
* @param edgeProvider Provider to create an edge
* @param updater Method used to update an existing Vertex
* @param vertexUpdater Method used to update an existing Vertex
*/
public DOTImporter(
VertexProvider<V> vertexProvider, EdgeProvider<V, E> edgeProvider, VertexUpdater<V> updater)
VertexProvider<V> vertexProvider, EdgeProvider<V, E> edgeProvider, ComponentUpdater<V> vertexUpdater)
{
this.vertexProvider = vertexProvider;
this.vertexUpdater = updater;
this.vertexUpdater = vertexUpdater;
this.edgeProvider = edgeProvider;
}

Expand Down Expand Up @@ -537,7 +537,7 @@ private void processCompleteNode(String node, Graph<V, E> graph, Map<String, V>
vertexes.put(id, vertex);
} else {
if (vertexUpdater != null) {
vertexUpdater.updateVertex(existing, attributes);
vertexUpdater.update(existing, attributes);
} else {
throw new ImportException(
"Update required for vertex " + id + " but no vertexUpdater provided");
Expand Down
Loading

0 comments on commit 30dade5

Please sign in to comment.