package com.tinkerpop.blueprints.impls.neo4j2;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import org.neo4j.graphdb.DynamicLabel;
import org.neo4j.graphdb.DynamicRelationshipType;
import org.neo4j.graphdb.Label;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.RelationshipType;
import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.blueprints.VertexQuery;
import com.tinkerpop.blueprints.impls.neo4j2.Neo4j2Graph.ElementWrapper;
import com.tinkerpop.blueprints.impls.neo4j2.iterate.Neo4j2EdgeIterable;
import com.tinkerpop.blueprints.impls.neo4j2.iterate.Neo4j2ElementIterable;
import com.tinkerpop.blueprints.util.DefaultVertexQuery;
import com.tinkerpop.blueprints.util.MultiIterable;
import com.tinkerpop.blueprints.util.StringFactory;
/**
* @author Marko A. Rodriguez (http://markorodriguez.com)
*/
public class Neo4j2Vertex extends Neo4j2Element<Node> implements Vertex {
private ElementWrapper<Neo4j2Vertex, Relationship> adjacentVertexWrapper = null;
public Neo4j2Vertex(final Node node, final Neo4j2Graph graph) {
super(graph);
this.rawElement = node;
}
public Iterable<Edge> getEdges(final Direction direction, final String... labels) {
if (direction.equals(Direction.OUT) || direction.equals(Direction.IN)){
return new Neo4j2EdgeIterable(getRelationships(direction, labels), graph);
} else {
return new MultiIterable<Edge>(Arrays.asList((Iterable<Edge>)
new Neo4j2EdgeIterable(getRelationships(Direction.OUT, labels), graph),
new Neo4j2EdgeIterable(getRelationships(Direction.IN, labels), graph)));
}
}
public Iterable<Vertex> getVertices(final Direction direction, final String... labels) {
if (direction.equals(Direction.OUT) || direction.equals(Direction.IN)){
return new AdjacentVertexIterable(getRelationships(direction, labels), graph);
} else {
return new MultiIterable<Vertex>(Arrays.asList((Iterable<Vertex>)
new AdjacentVertexIterable(getRelationships(Direction.OUT, labels), graph),
new AdjacentVertexIterable(getRelationships(Direction.IN, labels), graph)));
}
}
public Edge addEdge(final String label, final Vertex vertex) {
return this.graph.addEdge(null, this, vertex, label);
}
public Collection<String> getLabels() {
this.graph.autoStartTransaction(false);
final Collection<String> labels = new ArrayList<String>();
for (Label label : getRawElement().getLabels()) {
labels.add(label.name());
}
return labels;
}
public void addLabel(String label) {
graph.autoStartTransaction(true);
getRawElement().addLabel(DynamicLabel.label(label));
}
public void removeLabel(String label) {
graph.autoStartTransaction(true);
getRawElement().removeLabel(DynamicLabel.label(label));
}
public VertexQuery query() {
this.graph.autoStartTransaction(false);
return new DefaultVertexQuery(this);
}
@Override
public void remove() {
this.graph.removeVertex(this);
}
public boolean equals(final Object object) {
return object instanceof Neo4j2Vertex && ((Neo4j2Vertex) object).getId().equals(this.getId());
}
public String toString() {
return StringFactory.vertexString(this);
}
/**
* Deprecated, use getRawElement() instead.
* @return The underlying Neo4j Node object.
*/
@Deprecated
public Node getRawVertex() {
return this.rawElement;
}
//-------------------------------------------------------------------------
// Private helpers ...
private Iterable<Relationship> getRelationships(final Direction direction, final String... labels){
this.graph.autoStartTransaction(false);
if(labels.length > 0){
return this.rawElement.getRelationships(toRawDirection(direction), toRelationshipTypes(labels));
} else {
return this.rawElement.getRelationships(toRawDirection(direction));
}
}
private RelationshipType[] toRelationshipTypes(final String... labels){
RelationshipType[] edgeLabels = new DynamicRelationshipType[labels.length];
for (int i = 0; i < labels.length; i++) {
edgeLabels[i] = DynamicRelationshipType.withName(labels[i]);
}
return edgeLabels;
}
private org.neo4j.graphdb.Direction toRawDirection(final Direction direction){
switch (direction) {
case OUT:
return org.neo4j.graphdb.Direction.OUTGOING;
case IN:
return org.neo4j.graphdb.Direction.INCOMING;
case BOTH:
return org.neo4j.graphdb.Direction.BOTH;
default:
throw new IllegalArgumentException();
}
}
private ElementWrapper<Neo4j2Vertex, Relationship> getAdjacentVertexWrapper(){
if(adjacentVertexWrapper == null){
adjacentVertexWrapper = new ElementWrapper<Neo4j2Vertex, Relationship>(){
@Override
public Neo4j2Vertex wrap(Relationship relationship) {
return new Neo4j2Vertex(relationship.getOtherNode(rawElement), graph);
}
};
}
return adjacentVertexWrapper;
}
private class AdjacentVertexIterable extends Neo4j2ElementIterable<Vertex, Relationship> {
public AdjacentVertexIterable(Iterable<Relationship> elements, final Neo4j2Graph graph) {
super(elements, graph, getAdjacentVertexWrapper());
}
}
}