A couple blueprints suggestions

8 views
Skip to first unread message

Paul Jackson

unread,
Jun 10, 2010, 9:55:01 PM6/10/10
to Gremlin-users
First, please correct me if there is a more appropriate channel for
submitting requests for the blueprints project. My suggestions are:

1) In GraphML, it would be nice to be able to control the name of the
graph. Right now,
com.tinkerpop.blueprints.pgm.parser.GraphMLWriter.outputGraph(line 48)
contains the line:
writer.writeAttribute(GraphMLTokens.ID, GraphMLTokens.G);
It would be nice if there were a way to assign names to graphs in
com.tinkerpop.blueprints.pgm.impls.neo4j.Neo4jGraph.Neo4jGraph() and
for that name to be used as the ID.

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

Thanks,
Paul Jackson

Peter Neubauer

unread,
Jun 11, 2010, 8:24:38 AM6/11/10
to gremli...@googlegroups.com
Paul,

On Fri, Jun 11, 2010 at 3:55 AM, Paul Jackson <paul_j...@g1.com> wrote:
> 1) In GraphML, it would be nice to be able to control the name of the
> graph.  Right now,
> com.tinkerpop.blueprints.pgm.parser.GraphMLWriter.outputGraph(line 48)
> contains the line:
> writer.writeAttribute(GraphMLTokens.ID, GraphMLTokens.G);
> It would be nice if there were a way to assign names to graphs in
> com.tinkerpop.blueprints.pgm.impls.neo4j.Neo4jGraph.Neo4jGraph() and
> for that name to be used as the ID.
I think, in this case Graph.getName() should be added to Graph.java,
so all graphs can have names. Sensible request IMHO. WDYT Marko?

> 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 at http://github.com/peterneubauer/blueprints
and we can pull it into the Tinkerpop branch if Marko approves?

Thanks for the comments!

/peter

Marko Rodriguez

unread,
Jun 11, 2010, 11:22:50 AM6/11/10
to gremli...@googlegroups.com
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 at http://github.com/peterneubauer/blueprints
> and we can pull it into the Tinkerpop branch if Marko approves?

This makes sense. I'll pull that.

Thanks guys,
Marko.

http://markorodriguez.com
http://pipes.tinkerpop.com

Marko Rodriguez

unread,
Jun 11, 2010, 11:52:52 AM6/11/10
to gremli...@googlegroups.com
Hi,

> This is added to my fork at http://github.com/peterneubauer/blueprints
> and we can pull it into the Tinkerpop branch if Marko approves?


Committed. Actually, I added the "getIndexService()" method, but not to Graph, but to Index.

graph.getIndex().getIndexService();

------------

Moreover, this is not a stable solution as we need to think a bit harder about our object model. In principle we can generic Graph and Index such that we can have a unified method for all implementations -- e.g.:

Index<IndexService> getRawIndex()
Graph<GraphDatabaseService> getRawGraph();

For now its NOT like above, but beware of changes into the future which will be more elegant than these "one off" method solutions.

Take care,
Marko.

http://markorodriguez.com
http://rexster.tinkerpop.com

Paul Jackson

unread,
Jun 14, 2010, 1:08:31 PM6/14/10
to Gremlin-users
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
Reply all
Reply to author
Forward
0 new messages