org.jgrapht.ext.DOTExporter Maven / Gradle / Ivy
/*
* (C) Copyright 2006-2016, by Trevor Harmon 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.io.*;
import java.util.*;
import org.jgrapht.*;
/**
* Exports a graph into a DOT file.
*
*
* For a description of the format see
* http://en.wikipedia.org/wiki/DOT_language.
*
*
* @param the graph vertex type
* @param the graph edge type
*
* @author Trevor Harmon
*/
public class DOTExporter
implements GraphExporter
{
private VertexNameProvider vertexIDProvider;
private VertexNameProvider vertexLabelProvider;
private EdgeNameProvider edgeLabelProvider;
private ComponentAttributeProvider vertexAttributeProvider;
private ComponentAttributeProvider edgeAttributeProvider;
/**
* Constructs a new DOTExporter object with an integer name provider for the vertex IDs and null
* providers for the vertex and edge labels.
*/
public DOTExporter()
{
this(new IntegerNameProvider<>(), null, null);
}
/**
* Constructs a new DOTExporter object with the given ID and label providers.
*
* @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.
* @param edgeLabelProvider for generating edge labels. If null, edge labels will not be written
* to the file.
*/
public DOTExporter(
VertexNameProvider vertexIDProvider, VertexNameProvider vertexLabelProvider,
EdgeNameProvider edgeLabelProvider)
{
this(vertexIDProvider, vertexLabelProvider, edgeLabelProvider, null, null);
}
/**
* Constructs a new DOTExporter object with the given ID, label, and attribute 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.
*/
public DOTExporter(
VertexNameProvider vertexIDProvider, VertexNameProvider vertexLabelProvider,
EdgeNameProvider edgeLabelProvider,
ComponentAttributeProvider vertexAttributeProvider,
ComponentAttributeProvider edgeAttributeProvider)
{
this.vertexIDProvider = vertexIDProvider;
this.vertexLabelProvider = vertexLabelProvider;
this.edgeLabelProvider = edgeLabelProvider;
this.vertexAttributeProvider = vertexAttributeProvider;
this.edgeAttributeProvider = edgeAttributeProvider;
}
/**
* Exports a graph into a plain text file in DOT format.
*
* @param writer the writer to which the graph to be exported
* @param g the graph to be exported
*/
@Deprecated
public void export(Writer writer, Graph g)
{
exportGraph(g, writer);
}
/**
* Exports a graph into a plain text file in DOT format.
*
* @param g the graph to be exported
* @param writer the writer to which the graph to be exported
*/
@Override
public void exportGraph(Graph g, Writer writer)
{
PrintWriter out = new PrintWriter(writer);
String indent = " ";
String connector;
if (g instanceof DirectedGraph, ?>) {
out.println("digraph G {");
connector = " -> ";
} else {
out.println("graph G {");
connector = " -- ";
}
for (V v : g.vertexSet()) {
out.print(indent + getVertexID(v));
String labelName = null;
if (vertexLabelProvider != null) {
labelName = vertexLabelProvider.getVertexName(v);
}
Map attributes = null;
if (vertexAttributeProvider != null) {
attributes = vertexAttributeProvider.getComponentAttributes(v);
}
renderAttributes(out, labelName, attributes);
out.println(";");
}
for (E e : g.edgeSet()) {
String source = getVertexID(g.getEdgeSource(e));
String target = getVertexID(g.getEdgeTarget(e));
out.print(indent + source + connector + target);
String labelName = null;
if (edgeLabelProvider != null) {
labelName = edgeLabelProvider.getEdgeName(e);
}
Map attributes = null;
if (edgeAttributeProvider != null) {
attributes = edgeAttributeProvider.getComponentAttributes(e);
}
renderAttributes(out, labelName, attributes);
out.println(";");
}
out.println("}");
out.flush();
}
private void renderAttributes(PrintWriter out, String labelName, Map attributes)
{
if ((labelName == null) && (attributes == null)) {
return;
}
out.print(" [ ");
if ((labelName == null)) {
labelName = attributes.get("label");
}
if (labelName != null) {
out.print("label=\"" + labelName + "\" ");
}
if (attributes != null) {
for (Map.Entry entry : attributes.entrySet()) {
String name = entry.getKey();
if (name.equals("label")) {
// already handled by special case above
continue;
}
out.print(name + "=\"" + entry.getValue() + "\" ");
}
}
out.print("]");
}
/**
* Return a valid vertex ID (with respect to the .dot language definition as described in
* http://www.graphviz.org/doc/info/lang.html Quoted from above mentioned source: An ID is valid
* if it meets one of the following criteria:
*
*
* - any string of alphabetic characters, underscores or digits, not beginning with a digit;
*
- a number [-]?(.[0-9]+ | [0-9]+(.[0-9]*)? );
*
- any double-quoted string ("...") possibly containing escaped quotes (\");
*
- an HTML string (<...>).
*
*
* @throws RuntimeException if the given vertexIDProvider
didn't generate a valid
* vertex ID.
*/
private String getVertexID(V v)
{
// TODO jvs 28-Jun-2008: possible optimizations here are
// (a) only validate once per vertex
// (b) compile regex patterns
// use the associated id provider for an ID of the given vertex
String idCandidate = vertexIDProvider.getVertexName(v);
// now test that this is a valid ID
boolean isAlphaDig = idCandidate.matches("[a-zA-Z]+([\\w_]*)?");
boolean isDoubleQuoted = idCandidate.matches("\".*\"");
boolean isDotNumber = idCandidate.matches("[-]?([.][0-9]+|[0-9]+([.][0-9]*)?)");
boolean isHTML = idCandidate.matches("<.*>");
if (isAlphaDig || isDotNumber || isDoubleQuoted || isHTML) {
return idCandidate;
}
throw new RuntimeException(
"Generated id '" + idCandidate + "'for vertex '" + v
+ "' is not valid with respect to the .dot language");
}
}
// End DOTExporter.java
© 2015 - 2025 Weber Informatics LLC | Privacy Policy