All Downloads are FREE. Search and download functionalities are using the official Maven repository.

apoc.path.RelationshipSequenceExpander Maven / Gradle / Ivy

There is a newer version: 4.4.0.34
Show newest version
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