apoc.path.RelationshipSequenceExpander Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of apoc Show documentation
Show all versions of apoc Show documentation
A collection of useful Neo4j Procedures
package apoc.path;
import org.neo4j.graphdb.*;
import org.neo4j.graphdb.traversal.BranchState;
import org.neo4j.helpers.collection.Iterators;
import org.neo4j.helpers.collection.NestingIterator;
import org.neo4j.helpers.collection.Pair;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* An expander for repeating sequences of relationships. The sequence provided should be a string consisting of
* relationship type/direction patterns (exactly the same as the `relationshipFilter`), separated by commas.
* Each comma-separated pattern represents the relationships that will be expanded with each step of expansion, which
* repeats indefinitely (unless otherwise stopped by `maxLevel`, `limit`, or terminator filtering from the other expander config options).
* The exception is if `beginSequenceAtStart` is false. This indicates that the sequence should not begin from the start node,
* but from one node distant. In this case, we may still need a restriction on the relationship used to reach the start node
* of the sequence, so when `beginSequenceAtStart` is false, then the first relationship step in the sequence given will not
* actually be used as part of the sequence, but will only be used once to reach the starting node of the sequence.
* The remaining relationship steps will be used as the repeating relationship sequence.
*/
public class RelationshipSequenceExpander implements PathExpander {
private final List>> relSequences = new ArrayList<>();
private List> initialRels = null;
public RelationshipSequenceExpander(String relSequenceString, boolean beginSequenceAtStart) {
int index = 0;
for (String sequenceStep : relSequenceString.split(",")) {
sequenceStep = sequenceStep.trim();
Iterable> relDirIterable = RelationshipTypeAndDirections.parse(sequenceStep);
List> stepRels = new ArrayList<>();
for (Pair pair : relDirIterable) {
stepRels.add(pair);
}
if (!beginSequenceAtStart && index == 0) {
initialRels = stepRels;
} else {
relSequences.add(stepRels);
}
index++;
}
}
public RelationshipSequenceExpander(List relSequenceList, boolean beginSequenceAtStart) {
int index = 0;
for (String sequenceStep : relSequenceList) {
sequenceStep = sequenceStep.trim();
Iterable> relDirIterable = RelationshipTypeAndDirections.parse(sequenceStep);
List> stepRels = new ArrayList<>();
for (Pair pair : relDirIterable) {
stepRels.add(pair);
}
if (!beginSequenceAtStart && index == 0) {
initialRels = stepRels;
} else {
relSequences.add(stepRels);
}
index++;
}
}
@Override
public Iterable expand( Path path, BranchState state ) {
final Node node = path.endNode();
int depth = path.length();
List> stepRels;
if (depth == 0 && initialRels != null) {
stepRels = initialRels;
} else {
stepRels = relSequences.get((initialRels == null ? depth : depth - 1) % relSequences.size());
}
return Iterators.asList(
new NestingIterator>(
stepRels.iterator() )
{
@Override
protected Iterator createNestedIterator(
Pair entry )
{
RelationshipType type = entry.first();
Direction dir = entry.other();
if (type != null) {
return ((dir == Direction.BOTH) ? node.getRelationships(type) :
node.getRelationships(type, dir)).iterator();
} else {
return ((dir == Direction.BOTH) ? node.getRelationships() :
node.getRelationships(dir)).iterator();
}
}
});
}
@Override
public PathExpander reverse() {
throw new RuntimeException("Not implemented");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy