public List generateCanonicalPaths()

in asterix-graphix/src/main/java/org/apache/asterix/graphix/lang/rewrite/canonical/CanonicalElementGeneratorFactory.java [111:188]


    public List<PathPatternExpr> generateCanonicalPaths(EdgePatternExpr edgePatternExpr,
            boolean minimizeExpansionLength) throws CompilationException {
        EdgeDescriptor edgeDescriptor = edgePatternExpr.getEdgeDescriptor();
        VertexPatternExpr leftVertex = edgePatternExpr.getLeftVertex();
        VertexPatternExpr rightVertex = edgePatternExpr.getRightVertex();
        VertexPatternExpr internalVertex = edgePatternExpr.getInternalVertex();

        // Each variable below represents a loop nesting.
        Set<ElementLabel> edgeLabelList = edgeDescriptor.getEdgeLabels();
        Set<ElementLabel> leftLabelList = leftVertex.getLabels();
        Set<ElementLabel> rightLabelList = rightVertex.getLabels();
        Set<EdgeDirection> directionList = expandEdgeDirection(edgeDescriptor);
        Set<ElementLabel> internalLabelList = internalVertex.getLabels();

        // Determine the length of **expanded** path. For {N,M} w/ E labels... MIN(M, (1 + 2(E-1))).
        int minimumExpansionLength, expansionLength;
        if (minimizeExpansionLength) {
            int maximumExpansionLength = 1 + 2 * (edgeLabelList.size() - 1);
            minimumExpansionLength = Objects.requireNonNullElse(edgeDescriptor.getMinimumHops(), 1);
            expansionLength = Objects.requireNonNullElse(edgeDescriptor.getMaximumHops(), maximumExpansionLength);
            if (minimumExpansionLength > expansionLength) {
                minimumExpansionLength = expansionLength;
            }

        } else {
            minimumExpansionLength = Objects.requireNonNullElse(edgeDescriptor.getMinimumHops(), 1);
            expansionLength = edgeDescriptor.getMaximumHops();
        }

        // Generate all valid paths, from minimumExpansionLength to maximumExpansionLength.
        List<List<EdgePatternExpr>> canonicalPathList = new ArrayList<>();
        IInternalVertexSupplier internalVertexSupplier = () -> {
            VertexPatternExpr internalVertexCopy = deepCopyVisitor.visit(internalVertex, null);
            VariableExpr internalVariable = internalVertex.getVariableExpr();
            VariableExpr internalVariableCopy = graphixRewritingContext.getGraphixVariableCopy(internalVariable);
            internalVertexCopy.setVariableExpr(internalVariableCopy);
            return internalVertexCopy;
        };
        for (int pathLength = minimumExpansionLength; pathLength <= expansionLength; pathLength++) {
            List<List<EdgePatternExpr>> expandedPathPattern = expandFixedPathPattern(pathLength, edgePatternExpr,
                    edgeLabelList, internalLabelList, directionList, deepCopyVisitor, internalVertexSupplier);
            for (List<EdgePatternExpr> pathPattern : expandedPathPattern) {
                for (ElementLabel leftLabel : leftLabelList) {
                    for (ElementLabel rightLabel : rightLabelList) {
                        List<EdgePatternExpr> pathCopy = deepCopyPathPattern(pathPattern, deepCopyVisitor);

                        // Set the labels of our leftmost vertex...
                        pathCopy.get(0).getLeftVertex().getLabels().clear();
                        pathCopy.get(0).getLeftVertex().getLabels().add(leftLabel);

                        // ...and our rightmost vertex.
                        pathCopy.get(pathCopy.size() - 1).getRightVertex().getLabels().clear();
                        pathCopy.get(pathCopy.size() - 1).getRightVertex().getLabels().add(rightLabel);

                        // Add our path if all edges are valid.
                        if (pathCopy.stream().allMatch(schemaKnowledgeTable::isValidEdge)) {
                            canonicalPathList.add(pathCopy);
                        }
                    }
                }
            }
        }

        // Wrap our edge lists into path patterns.
        List<PathPatternExpr> pathPatternList = new ArrayList<>();
        for (List<EdgePatternExpr> edgeList : canonicalPathList) {
            List<VertexPatternExpr> vertexList = new ArrayList<>();
            edgeList.forEach(e -> {
                vertexList.add(e.getLeftVertex());
                vertexList.add(e.getRightVertex());
            });
            VariableExpr variableExpr = deepCopyVisitor.visit(edgeDescriptor.getVariableExpr(), null);
            PathPatternExpr pathPatternExpr = new PathPatternExpr(vertexList, edgeList, variableExpr);
            pathPatternExpr.setSourceLocation(edgePatternExpr.getSourceLocation());
            pathPatternList.add(pathPatternExpr);
        }
        return pathPatternList;
    }