I'm having an issue with rendering a Jung graph - the graph is creating duplicate nodes for some reason.
I load the nodes (two different types into a custom Vertex class (MovieVertex extends RootNode implements NodeInfo and PersonVertex extends RootNode implements NodeInfo) - RootNode has a name field that I display on the vertex label using the following code:
DirectedSparseGraph<NodeInfo,String> g = new DirectedSparseGraph<NodeInfo, String>();
// Code to read node data from a Neo4j graph database
List<Map<String, Object>> nodes = grapher.read(cql);
try (Session session = grapher.driver.session()){
StatementResult result = session.run(cql2);
while (result.hasNext()) {
Record record = result.next();
String targetNode = record.get(1).get("title").toString();
String sourceNode = record.get(0).get("name").toString();
String tagline = record.get(1).get("tagline").toString();
String released = record.get(1).get("released").toString();
int born = record.get(0).get("born").asInt();
String rel = sourceNode + "-ACTED_IN-"+ targetNode;
//The problem is probably here - it is creating duplicate vertices for the same data
MovieVertex mv = new MovieVertex(targetNode,tagline,released);
PersonVertex pv = new PersonVertex(sourceNode,born);
g.addVertex(pv);
g.addVertex(mv);
g.addEdge(rel, pv, mv);
ISOMLayout<NodeInfo,String> layout = new ISOMLayout<NodeInfo,String>(g);
VisualizationViewer<NodeInfo,String> vv =
new VisualizationViewer<NodeInfo,String>(layout, new Dimension(800,800));
vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller());
JFrame frame = new JFrame();
frame.getContentPane().add(vv);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
Edit: I added the following code to the Vertex custom classes to address the problem, updated graph example:
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof MovieVertex)) {
return false;
}
MovieVertex mv = (MovieVertex) o;
return new EqualsBuilder()
.append(title, mv.title)
.append(tagline, mv.tagline)
.append(released, mv.released)
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(title)
.append(tagline)
.append(released)
.toHashCode();
}
This is a common problem with any custom Java class that is used as a Map
key (as JUNG Vertices are). Unless you override the equals
and hashCode
method in your custom Vertex class, you will get duplicates. You would see the same problem if you added your MovieVertex
or PersonVertex
instances to a java.util.Set
or used them as keys in a Map.
Perhaps you can use your name field to compute the value for hashCode and to determine when the Vertices are equal.