Hi Marko,
I am confused by "best left to people wanting to override those
methods with their custom output". I concur that my request is
special purpose and would like to pursue an override approach, but
unless I am missing something, there is no clean way to do this. I
understood your suggestion to mean that I would do something like
this:
class MyGraphMLWriter extends GraphMLWriter {
public static void outputGraph(final Graph graph,
final OutputStream
graphMLOutputStream,
final Map<String, String>
vertexKeyTypes,
final Map<String, String>
edgeKeyTypes)
{
...
}
}
This leads to a duplication of 90% of the code contained in the base
class. I prefer to avoid this for two reasons - I would like to
benefit from any future enhancements in the base class, and I am
concerned about violating the license agreement. My company is
discussing using a tool to match our source against known open source
and if I write the class using your class as a guide I should think
the tool would flag mine as a violation.
From my perspective, outputGraph would be an instance method that
called out to a set of template methods:
class GraphMLWriter
{
protected Graph graph;
protected OutputStream graphMLOutputStream;
protected XMLStreamWriter writer;
public GraphMLWriter(Graph graph, OutputStream graphMLOutputStream,
XMLStreamWriter writer)
{
this.graph = graph;
this.graphMLOutputStream = graphMLOutputStream;
this.writer = writer;
}
// Retaining static method for backward compatibility
public static void outputGraph(final Graph graph,
final OutputStream
graphMLOutputStream,
final Map<String, String>
vertexKeyTypes,
final Map<String, String>
edgeKeyTypes)
throws XMLStreamException
{
XMLOutputFactory inputFactory = XMLOutputFactory.newInstance();
XMLStreamWriter writer =
inputFactory.createXMLStreamWriter(graphMLOutputStream);
GraphMLWriter graphMLWriter = new GraphMLWriter(graph,
graphMLOutputStream, writer);
graphMLWriter.outputGraphMethod(vertexKeyTypes, edgeKeyTypes);
}
// New instance method. Could be protected rather than public
public void outputGraphMethod(final Map<String, String>
vertexKeyTypes,
final Map<String, String> edgeKeyTypes)
throws XMLStreamException
{
XMLOutputFactory inputFactory = XMLOutputFactory.newInstance();
writer = inputFactory.createXMLStreamWriter(graphMLOutputStream);
writeStartDocument();
writeStartElement(GraphMLTokens.GRAPHML);
writeAttribute(GraphMLTokens.XMLNS, GraphMLTokens.GRAPHML_XMLNS);
//<key id="weight" for="edge"
attr.name="weight" attr.type="float"/
>
writeNodesSchema(vertexKeyTypes);
writeEdgesSchema(edgeKeyTypes);
writeStartElement(GraphMLTokens.GRAPH);
writeAttribute(GraphMLTokens.ID, GraphMLTokens.G);
writeAttribute(GraphMLTokens.EDGEDEFAULT, GraphMLTokens.DIRECTED);
for (Vertex vertex : graph.getVertices()) {
writeStartElement(GraphMLTokens.NODE);
writeAttribute(GraphMLTokens.ID, vertex.getId().toString());
for (String key : vertex.getPropertyKeys()) {
writeStartElement(GraphMLTokens.DATA);
writeAttribute(GraphMLTokens.KEY, key);
writeCharacters(vertex.getProperty(key).toString());
writeEndElement();
}
writeEndElement();
}
for (Vertex vertex : graph.getVertices()) {
for (Edge edge : vertex.getOutEdges()) {
writeStartElement(GraphMLTokens.EDGE);
writeAttribute(GraphMLTokens.ID, edge.getId().toString());
writeAttribute(GraphMLTokens.SOURCE,
edge.getOutVertex().getId().toString());
writeAttribute(GraphMLTokens.TARGET,
edge.getInVertex().getId().toString());
writeAttribute(GraphMLTokens.LABEL, edge.getLabel());
for (String key : edge.getPropertyKeys()) {
writeStartElement(GraphMLTokens.DATA);
writeAttribute(GraphMLTokens.KEY, key);
writeCharacters(edge.getProperty(key).toString());
writeEndElement();
}
writeEndElement();
}
}
writeEndElement();
writeEndElement();
writeEndDocument();
writer.flush();
writer.close();
}
protected void writeNodesSchema(final Map<String, String>
vertexKeyTypes)
throws XMLStreamException
{
for (Map.Entry<String, String> entry : vertexKeyTypes.entrySet())
{
writeNodeSchema(entry);
}
}
protected void writeNodeSchema(Map.Entry<String, String> entry)
throws XMLStreamException
{
writeStartElement(GraphMLTokens.KEY);
writeAttribute(GraphMLTokens.ID, entry.getKey());
writeAttribute(GraphMLTokens.FOR, GraphMLTokens.NODE);
writeAttribute(GraphMLTokens.ATTR_NAME, entry.getKey());
writeAttribute(GraphMLTokens.ATTR_TYPE, entry.getValue());
writeEndElement();
}
protected void writeEdgesSchema(Map<String, String> edgeKeyTypes)
throws XMLStreamException
{
for (Map.Entry<String, String> entry : edgeKeyTypes.entrySet()) {
writeEdgeSchema(entry);
}
}
protected void writeEdgeSchema(Map.Entry<String, String> entry)
throws XMLStreamException
{
writeStartElement(GraphMLTokens.KEY);
writeAttribute(GraphMLTokens.ID, entry.getKey());
writeAttribute(GraphMLTokens.FOR, GraphMLTokens.EDGE);
writeAttribute(GraphMLTokens.ATTR_NAME, entry.getKey());
writeAttribute(GraphMLTokens.ATTR_TYPE, entry.getValue());
writeEndElement();
}
protected void writeStartDocument() throws XMLStreamException
{
writer.writeStartDocument();
}
protected void writeStartElement(String localName)
throws XMLStreamException
{
writer.writeStartElement(localName);
}
protected void writeAttribute(String localName, String value)
throws XMLStreamException
{
writer.writeAttribute(localName, value);
}
protected void writeCharacters(String text) throws
XMLStreamException
{
writer.writeCharacters(text);
}
protected void writeEndElement() throws XMLStreamException
{
writer.writeEndElement();
}
protected void writeEndDocument()throws XMLStreamException
{
writer.writeEndDocument();
}
}
--------------------------------------------------
I could write a class that extends this implementation of
GraphMLWriter and override only one method:
public class MyGraphMLWriter extends GraphMLWriter {
public MyGraphMLWriter(Graph graph, OutputStream
graphMLOutputStream, XMLStreamWriter writer)
{
super(graph, graphMLOutputStream, writer);
}
@Override
protected void writeAttribute(String localName, String value) throws
XMLStreamException
{
if (GraphMLTokens.ID.equals(localName) && graph.getName() != null
&& !graph.getName().trim().equals(""))
{
super.writeAttribute(localName, graph.getName());
}
else
{
super.writeAttribute(localName, value);
}
}
}
Your thoughts?
Thanks,
Paul Jackson
On Jun 11, 11:22 am, Marko Rodriguez <
okramma...@gmail.com> wrote:
> Hello,
>
> > I think, in this case Graph.getName() should be added to Graph.java,
> > so all graphs can have names. Sensible request IMHO. WDYT Marko?
>
> Hmmm... Why? Just so the GraphML output <graph> has a name attribute? Perhaps what would be better would be to allow people to specify a String name when calling GraphMLWriter.outputGraph(). However, that is pretty special purpose and, I believe, best left to people wanting to override those methods with their custom output.
>
> >> 2) In the same way that the 0.1.2-SNAPSHOT release added this method
> >> to the Neo4jGraph class:
> >> public GraphDatabaseService getGraphDatabaseService() {
> >> return this.neo;
> >> }
> >> It would also be nice to see the following added to Neo4jIndex:
> >> public IndexService getIndexService() {
> >> return this.indexService;
> >> }
> > This is added to my fork athttp://
github.com/peterneubauer/blueprints