* @author Joshua Shinavier (http://fortytwo.net)
*/
public class GraphMLWriter {
<<<<<<< HEAD
private final Graph graph;
private boolean normalize = false;
private Map vertexKeyTypes = null;
private Map edgeKeyTypes = null;
/**
* @param graph the Graph to pull the data from
*/
public GraphMLWriter(final Graph graph) {
this.graph = graph;
}
/**
* @param normalize whether to normalize the output.
* Normalized output is deterministic with respect to the order of elements and properties in the resulting XML document,
* and is compatible with line diff-based tools such as Git.
* Note: normalized output is memory-intensive and is not appropriate for very large graphs.
*/
public void setNormalize(final boolean normalize) {
this.normalize = normalize;
}
/**
* @param vertexKeyTypes a Map of the data types of the vertex keys
*/
public void setVertexKeyTypes(final Map vertexKeyTypes) {
this.vertexKeyTypes = vertexKeyTypes;
}
/**
* @param edgeKeyTypes a Map of the data types of the edge keys
*/
public void setEdgeKeyTypes(final Map edgeKeyTypes) {
this.edgeKeyTypes = edgeKeyTypes;
}
/**
* Write the data in a Graph to a GraphML OutputStream.
*
* @param graphMLOutputStream the GraphML OutputStream to write the Graph data to
* @throws IOException thrown if there is an error generating the GraphML data
*/
public void outputGraph(final OutputStream graphMLOutputStream) throws IOException {
if (null == this.vertexKeyTypes || null == this.edgeKeyTypes) {
Map vertexKeyTypes = new HashMap();
Map edgeKeyTypes = new HashMap();
for (Vertex vertex : graph.getVertices()) {
for (String key : vertex.getPropertyKeys()) {
if (!vertexKeyTypes.containsKey(key)) {
vertexKeyTypes.put(key, GraphMLWriter.getStringType(vertex.getProperty(key)));
}
}
for (Edge edge : vertex.getOutEdges()) {
for (String key : edge.getPropertyKeys()) {
if (!edgeKeyTypes.containsKey(key)) {
edgeKeyTypes.put(key, GraphMLWriter.getStringType(edge.getProperty(key)));
}
}
}
}
if (null == this.vertexKeyTypes) {
this.vertexKeyTypes = vertexKeyTypes;
}
if (null == this.edgeKeyTypes) {
this.edgeKeyTypes = edgeKeyTypes;
}
}
XMLOutputFactory inputFactory = XMLOutputFactory.newInstance();
try {
XMLStreamWriter writer = inputFactory.createXMLStreamWriter(graphMLOutputStream, "UTF8");
if (normalize) {
writer = new GraphMLWriterHelper.IndentingXMLStreamWriter(writer);
((GraphMLWriterHelper.IndentingXMLStreamWriter) writer).setIndentStep(" ");
}
writer.writeStartDocument();
writer.writeStartElement(GraphMLTokens.GRAPHML);
writer.writeAttribute(GraphMLTokens.XMLNS, GraphMLTokens.GRAPHML_XMLNS);
//
Collection keyset;
if (normalize) {
keyset = new LinkedList();
keyset.addAll(vertexKeyTypes.keySet());
Collections.sort((List) keyset);
} else {
keyset = vertexKeyTypes.keySet();
}
for (String key : keyset) {
writer.writeStartElement(GraphMLTokens.KEY);
writer.writeAttribute(GraphMLTokens.ID, key);
writer.writeAttribute(GraphMLTokens.FOR, GraphMLTokens.NODE);
writer.writeAttribute(GraphMLTokens.ATTR_NAME, key);
writer.writeAttribute(GraphMLTokens.ATTR_TYPE, vertexKeyTypes.get(key));
writer.writeEndElement();
}
if (normalize) {
keyset = new LinkedList();
keyset.addAll(edgeKeyTypes.keySet());
Collections.sort((List) keyset);
} else {
keyset = edgeKeyTypes.keySet();
}
for (String key : keyset) {
writer.writeStartElement(GraphMLTokens.KEY);
writer.writeAttribute(GraphMLTokens.ID, key);
writer.writeAttribute(GraphMLTokens.FOR, GraphMLTokens.EDGE);
writer.writeAttribute(GraphMLTokens.ATTR_NAME, key);
writer.writeAttribute(GraphMLTokens.ATTR_TYPE, edgeKeyTypes.get(key));
writer.writeEndElement();
}
writer.writeStartElement(GraphMLTokens.GRAPH);
writer.writeAttribute(GraphMLTokens.ID, GraphMLTokens.G);
writer.writeAttribute(GraphMLTokens.EDGEDEFAULT, GraphMLTokens.DIRECTED);
Iterable vertices;
if (normalize) {
vertices = new LinkedList();
for (Vertex v : graph.getVertices()) {
((Collection) vertices).add(v);
}
Collections.sort((List) vertices, new ElementComparator());
} else {
vertices = graph.getVertices();
}
for (Vertex vertex : vertices) {
writer.writeStartElement(GraphMLTokens.NODE);
writer.writeAttribute(GraphMLTokens.ID, vertex.getId().toString());
Collection keys;
if (normalize) {
keys = new LinkedList();
keys.addAll(vertex.getPropertyKeys());
Collections.sort((List) keys);
} else {
keys = vertex.getPropertyKeys();
}
for (String key : keys) {
writer.writeStartElement(GraphMLTokens.DATA);
writer.writeAttribute(GraphMLTokens.KEY, key);
Object value = vertex.getProperty(key);
if (null != value)
writer.writeCharacters(value.toString());
writer.writeEndElement();
}
writer.writeEndElement();
}
if (normalize) {
List edges = new LinkedList();
for (Vertex vertex : graph.getVertices()) {
for (Edge edge : vertex.getOutEdges()) {
edges.add(edge);
}
}
Collections.sort(edges, new ElementComparator());
for (Edge edge : edges) {
writer.writeStartElement(GraphMLTokens.EDGE);
writer.writeAttribute(GraphMLTokens.ID, edge.getId().toString());
writer.writeAttribute(GraphMLTokens.SOURCE, edge.getOutVertex().getId().toString());
writer.writeAttribute(GraphMLTokens.TARGET, edge.getInVertex().getId().toString());
writer.writeAttribute(GraphMLTokens.LABEL, edge.getLabel());
List keys = new LinkedList();
keys.addAll(edge.getPropertyKeys());
Collections.sort(keys);
for (String key : keys) {
writer.writeStartElement(GraphMLTokens.DATA);
writer.writeAttribute(GraphMLTokens.KEY, key);
Object value = edge.getProperty(key);
if (null != value)
writer.writeCharacters(value.toString());
writer.writeEndElement();
}
writer.writeEndElement();
}
} else {
for (Vertex vertex : graph.getVertices()) {
for (Edge edge : vertex.getOutEdges()) {
writer.writeStartElement(GraphMLTokens.EDGE);
writer.writeAttribute(GraphMLTokens.ID, edge.getId().toString());
writer.writeAttribute(GraphMLTokens.SOURCE, edge.getOutVertex().getId().toString());
writer.writeAttribute(GraphMLTokens.TARGET, edge.getInVertex().getId().toString());
writer.writeAttribute(GraphMLTokens.LABEL, edge.getLabel());
for (String key : edge.getPropertyKeys()) {
writer.writeStartElement(GraphMLTokens.DATA);
writer.writeAttribute(GraphMLTokens.KEY, key);
Object value = edge.getProperty(key);
if (null != value)
writer.writeCharacters(value.toString());
writer.writeEndElement();
}
writer.writeEndElement();
}
}
}
writer.writeEndElement(); // graph
writer.writeEndElement(); // graphml
writer.writeEndDocument();
writer.flush();
writer.close();
} catch (XMLStreamException xse) {
throw new IOException(xse);
}
}
/**
* Write the data in a Graph to a GraphML OutputStream.
*
* @param graph the Graph to pull the data from
* @param graphMLOutputStream the GraphML OutputStream to write the Graph data to
* @throws IOException thrown if there is an error generating the GraphML data
*/
public static void outputGraph(final Graph graph, final OutputStream graphMLOutputStream) throws IOException {
GraphMLWriter writer = new GraphMLWriter(graph);
writer.outputGraph(graphMLOutputStream);
}
/**
* Write the data in a Graph to a GraphML OutputStream.
*
* @param graph the Graph to pull the data from
* @param graphMLOutputStream the GraphML OutputStream to write the Graph data to
* @param vertexKeyTypes a Map of the data types of the vertex keys
* @param edgeKeyTypes a Map of the data types of the edge keys
* @throws IOException thrown if there is an error generating the GraphML data
*/
public static void outputGraph(final Graph graph, final OutputStream graphMLOutputStream, final Map vertexKeyTypes, final Map edgeKeyTypes) throws IOException {
GraphMLWriter writer = new GraphMLWriter(graph);
writer.setVertexKeyTypes(vertexKeyTypes);
writer.setEdgeKeyTypes(edgeKeyTypes);
writer.outputGraph(graphMLOutputStream);
}
private static String getStringType(final Object object) {
if (object instanceof String)
return GraphMLTokens.STRING;
else if (object instanceof Integer)
return GraphMLTokens.INT;
else if (object instanceof Long)
return GraphMLTokens.LONG;
else if (object instanceof Float)
return GraphMLTokens.FLOAT;
else if (object instanceof Number)
return GraphMLTokens.DOUBLE;
else if (object instanceof Boolean)
return GraphMLTokens.BOOLEAN;
else
return GraphMLTokens.STRING;
}
// Note: elements are sorted in lexicographical, not in numerical, order of IDs.
private static class ElementComparator implements Comparator {
=======
private final Graph graph;
private boolean normalize = false;
private Map vertexKeyTypes = null;
private Map edgeKeyTypes = null;
/**
* @param graph
* the Graph to pull the data from
*/
public GraphMLWriter(final Graph graph) {
this.graph = graph;
}
/**
* @param normalize
* whether to normalize the output. Normalized output is deterministic with respect to the order of
* elements and properties in the resulting XML document, and is compatible with line diff-based tools
* such as Git. Note: normalized output is memory-intensive and is not appropriate for very large graphs.
*/
public void setNormalize(final boolean normalize) {
this.normalize = normalize;
}
/**
* @param vertexKeyTypes
* a Map of the data types of the vertex keys
*/
public void setVertexKeyTypes(final Map vertexKeyTypes) {
this.vertexKeyTypes = vertexKeyTypes;
}
/**
* @param edgeKeyTypes
* a Map of the data types of the edge keys
*/
}
public void setEdgeKeyTypes(final Map edgeKeyTypes) {
this.edgeKeyTypes = edgeKeyTypes;
}
/**
* Write the data in a Graph to a GraphML OutputStream.
*
* @param graphMLOutputStream
* the GraphML OutputStream to write the Graph data to
* @throws IOException
* thrown if there is an error generating the GraphML data
*/
public void outputGraph(final OutputStream graphMLOutputStream) throws IOException {
if (null == vertexKeyTypes || null == edgeKeyTypes) {
Map vertexKeyTypes = new HashMap();
Map edgeKeyTypes = new HashMap();
for (Vertex vertex : graph.getVertices()) {
for (String key : vertex.getPropertyKeys()) {
if (!vertexKeyTypes.containsKey(key)) {
vertexKeyTypes.put(key, GraphMLWriter.getStringType(vertex.getProperty(key)));
}
}
for (Edge edge : vertex.getOutEdges()) {
for (String key : edge.getPropertyKeys()) {
if (!edgeKeyTypes.containsKey(key)) {
edgeKeyTypes.put(key, GraphMLWriter.getStringType(edge.getProperty(key)));
}
}
}
}
if (null == this.vertexKeyTypes) {
this.vertexKeyTypes = vertexKeyTypes;
}
if (null == this.edgeKeyTypes) {
this.edgeKeyTypes = edgeKeyTypes;
}
}
XMLOutputFactory inputFactory = XMLOutputFactory.newInstance();
try {
XMLStreamWriter writer = inputFactory.createXMLStreamWriter(graphMLOutputStream, "UTF8");
if (normalize) {
writer = new GraphMLWriterHelper.IndentingXMLStreamWriter(writer);
((GraphMLWriterHelper.IndentingXMLStreamWriter) writer).setIndentStep(" ");
}
writer.writeStartDocument();
writer.writeStartElement(GraphMLTokens.GRAPHML);
writer.writeAttribute(GraphMLTokens.XMLNS, GraphMLTokens.GRAPHML_XMLNS);
//
Collection keyset;
if (normalize) {
keyset = new LinkedList();
keyset.addAll(vertexKeyTypes.keySet());
Collections.sort((List) keyset);
} else {
keyset = vertexKeyTypes.keySet();
}
for (String key : keyset) {
writer.writeStartElement(GraphMLTokens.KEY);
writer.writeAttribute(GraphMLTokens.ID, key);
writer.writeAttribute(GraphMLTokens.FOR, GraphMLTokens.NODE);
writer.writeAttribute(GraphMLTokens.ATTR_NAME, key);
writer.writeAttribute(GraphMLTokens.ATTR_TYPE, vertexKeyTypes.get(key));
writer.writeEndElement();
}
if (normalize) {
keyset = new LinkedList();
keyset.addAll(edgeKeyTypes.keySet());
Collections.sort((List) keyset);
} else {
keyset = edgeKeyTypes.keySet();
}
for (String key : keyset) {
writer.writeStartElement(GraphMLTokens.KEY);
writer.writeAttribute(GraphMLTokens.ID, key);
writer.writeAttribute(GraphMLTokens.FOR, GraphMLTokens.EDGE);
writer.writeAttribute(GraphMLTokens.ATTR_NAME, key);
writer.writeAttribute(GraphMLTokens.ATTR_TYPE, edgeKeyTypes.get(key));
writer.writeEndElement();
}
writer.writeStartElement(GraphMLTokens.GRAPH);
writer.writeAttribute(GraphMLTokens.ID, GraphMLTokens.G);
writer.writeAttribute(GraphMLTokens.EDGEDEFAULT, GraphMLTokens.DIRECTED);
Iterable vertices;
if (normalize) {
vertices = new LinkedList();
for (Vertex v : graph.getVertices()) {
((Collection) vertices).add(v);
Collections.sort((List) vertices, new LexicographicalElementComparator());
} else {
vertices = graph.getVertices();
}
for (Vertex vertex : vertices) {
writer.writeStartElement(GraphMLTokens.NODE);
writer.writeAttribute(GraphMLTokens.ID, vertex.getId().toString());
Collection keys;
if (normalize) {
keys = new LinkedList();
keys.addAll(vertex.getPropertyKeys());
Collections.sort((List) keys);
} else {
keys = vertex.getPropertyKeys();
}
for (String key : keys) {
writer.writeStartElement(GraphMLTokens.DATA);
writer.writeAttribute(GraphMLTokens.KEY, key);
Object value = vertex.getProperty(key);
if (null != value) {
writer.writeCharacters(value.toString());
}
writer.writeEndElement();
}
writer.writeEndElement();
}
if (normalize) {
List edges = new LinkedList();
for (Vertex vertex : graph.getVertices()) {
for (Edge edge : vertex.getOutEdges()) {
edges.add(edge);
}
}
Collections.sort(edges, new LexicographicalElementComparator());
for (Edge edge : edges) {
writer.writeStartElement(GraphMLTokens.EDGE);
writer.writeAttribute(GraphMLTokens.ID, edge.getId().toString());
writer.writeAttribute(GraphMLTokens.SOURCE, edge.getOutVertex().getId().toString());
writer.writeAttribute(GraphMLTokens.TARGET, edge.getInVertex().getId().toString());
writer.writeAttribute(GraphMLTokens.LABEL, edge.getLabel());
List keys = new LinkedList();
keys.addAll(edge.getPropertyKeys());
Collections.sort(keys);
for (String key : keys) {
writer.writeStartElement(GraphMLTokens.DATA);
writer.writeAttribute(GraphMLTokens.KEY, key);
Object value = edge.getProperty(key);
if (null != value) {
writer.writeCharacters(value.toString());
}
writer.writeEndElement();
}
writer.writeEndElement();
}
} else {
for (Vertex vertex : graph.getVertices()) {
for (Edge edge : vertex.getOutEdges()) {
writer.writeStartElement(GraphMLTokens.EDGE);
writer.writeAttribute(GraphMLTokens.ID, edge.getId().toString());
writer.writeAttribute(GraphMLTokens.SOURCE, edge.getOutVertex().getId().toString());
writer.writeAttribute(GraphMLTokens.TARGET, edge.getInVertex().getId().toString());
writer.writeAttribute(GraphMLTokens.LABEL, edge.getLabel());
for (String key : edge.getPropertyKeys()) {
writer.writeStartElement(GraphMLTokens.DATA);
writer.writeAttribute(GraphMLTokens.KEY, key);
Object value = edge.getProperty(key);
if (null != value) {
writer.writeCharacters(value.toString());
}
writer.writeEndElement();
}
writer.writeEndElement();
}
}
}
writer.writeEndElement(); // graph
writer.writeEndElement(); // graphml
writer.writeEndDocument();
writer.flush();
writer.close();
} catch (XMLStreamException xse) {
throw new IOException(xse);
}
}
/**
* Write the data in a Graph to a GraphML OutputStream.
*
* @param graph
* the Graph to pull the data from
* @param graphMLOutputStream
* the GraphML OutputStream to write the Graph data to
* @throws IOException
* thrown if there is an error generating the GraphML data
*/
public static void outputGraph(final Graph graph, final OutputStream graphMLOutputStream) throws IOException {
GraphMLWriter writer = new GraphMLWriter(graph);
writer.outputGraph(graphMLOutputStream);
}
/**
* Write the data in a Graph to a GraphML OutputStream.
*
* @param graph
* the Graph to pull the data from
* @param graphMLOutputStream
* the GraphML OutputStream to write the Graph data to
* @param vertexKeyTypes
* a Map of the data types of the vertex keys
* @param edgeKeyTypes
* a Map of the data types of the edge keys
* @throws IOException
* thrown if there is an error generating the GraphML data
*/
public static void outputGraph(final Graph graph, final OutputStream graphMLOutputStream,
final Map vertexKeyTypes, final Map edgeKeyTypes) throws IOException {
GraphMLWriter writer = new GraphMLWriter(graph);
writer.setVertexKeyTypes(vertexKeyTypes);
writer.setEdgeKeyTypes(edgeKeyTypes);
writer.outputGraph(graphMLOutputStream);
}
private static String getStringType(final Object object) {
if (object instanceof String) {
return GraphMLTokens.STRING;
} else if (object instanceof Integer) {
return GraphMLTokens.INT;
} else if (object instanceof Long) {
return GraphMLTokens.LONG;
} else if (object instanceof Float) {
return GraphMLTokens.FLOAT;
} else if (object instanceof Double) {
return GraphMLTokens.DOUBLE;
} else if (object instanceof Boolean) {
return GraphMLTokens.BOOLEAN;
} else {
return GraphMLTokens.STRING;
}
}
>>>>>>> 8c0d19e6fdddeae2ce9ac0c6e0a3b464aa5a48e8
} |