apoc.result.VirtualPath Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of apoc-common Show documentation
Show all versions of apoc-common Show documentation
Data types package for Neo4j Procedures
package apoc.result;
import org.neo4j.graphdb.Entity;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Path;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.traversal.Paths;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import static org.apache.commons.collections4.IterableUtils.reversedIterable;
public class VirtualPath implements Path {
private final Node start;
private final List relationships;
public VirtualPath(Node start) {
this(start, new ArrayList<>());
}
private VirtualPath(Node start, List relationships) {
Objects.requireNonNull(start);
Objects.requireNonNull(relationships);
this.start = start;
this.relationships = relationships;
}
public void addRel(Relationship relationship) {
Objects.requireNonNull(relationship);
requireConnected(relationship);
this.relationships.add(relationship);
}
@Override
public Node startNode() {
return start;
}
@Override
public Node endNode() {
return reverseNodes().iterator().next();
}
@Override
public Relationship lastRelationship() {
return relationships.isEmpty() ? null : relationships.get(relationships.size() - 1);
}
@Override
public Iterable relationships() {
return relationships;
}
@Override
public Iterable reverseRelationships() {
return reversedIterable(relationships());
}
@Override
public Iterable nodes() {
List nodes = new ArrayList<>();
nodes.add(start);
AtomicReference currNode = new AtomicReference<>(start);
final List otherNodes = relationships.stream().map(rel -> {
final Node otherNode = rel.getOtherNode(currNode.get());
currNode.set(otherNode);
return otherNode;
}).collect(Collectors.toList());
nodes.addAll(otherNodes);
return nodes;
}
@Override
public Iterable reverseNodes() {
return reversedIterable(nodes());
}
@Override
public int length() {
return relationships.size();
}
@Override
@Nonnull
public Iterator iterator() {
return new Iterator<>() {
Iterator extends Entity> current = nodes().iterator();
Iterator extends Entity> next = relationships().iterator();
@Override
public boolean hasNext() {
return current.hasNext();
}
@Override
public Entity next() {
try {
return current.next();
}
finally {
Iterator extends Entity> temp = current;
current = next;
next = temp;
}
}
@Override
public void remove() {
next.remove();
}
};
}
@Override
public String toString() {
return Paths.defaultPathToString(this);
}
private void requireConnected(Relationship relationship) {
Node previousEndNode;
Relationship previousRelationship = lastRelationship();
if (previousRelationship != null) {
previousEndNode = previousRelationship.getEndNode();
} else {
previousEndNode = endNode();
}
if (!relationship.getStartNode().equals(previousEndNode)
&& !relationship.getEndNode().equals(previousEndNode)) {
throw new IllegalArgumentException("Relationship is not part of current path.");
}
}
public static final class Builder {
private final Node start;
private final List relationships = new ArrayList<>();
public Builder(Node start) {
this.start = start;
}
public Builder push(Relationship relationship) {
this.relationships.add(relationship);
return this;
}
public VirtualPath build() {
return new VirtualPath(start, relationships);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy