private void lowerCanonicalExpandedEdge()

in asterix-graphix/src/main/java/org/apache/asterix/graphix/lang/rewrite/visitor/GraphixLoweringVisitor.java [258:365]


    private void lowerCanonicalExpandedEdge(EdgePatternExpr edgePatternExpr, LoweringEnvironment environment)
            throws CompilationException {
        EdgeDescriptor edgeDescriptor = edgePatternExpr.getEdgeDescriptor();

        // We should be working with a canonical edge.
        GraphIdentifier graphIdentifier = environment.getGraphIdentifier();
        List<EdgeIdentifier> edgeElementIDs = edgePatternExpr.generateIdentifiers(graphIdentifier);
        if (edgeElementIDs.size() != 1) {
            throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE,
                    "Encountered non-fixed-point edge pattern!");
        }
        EdgeIdentifier edgeIdentifier = edgeElementIDs.get(0);
        ElementBodyAnalysisContext edgeBodyAnalysisContext = analysisContextMap.get(edgeIdentifier);
        DataverseName edgeDataverseName = edgeBodyAnalysisContext.getDataverseName();
        String edgeDatasetName = edgeBodyAnalysisContext.getDatasetName();

        // Determine our source and destination vertices.
        VertexPatternExpr sourceVertex, destVertex;
        if (edgeDescriptor.getEdgeDirection() == EdgeDescriptor.EdgeDirection.LEFT_TO_RIGHT) {
            sourceVertex = edgePatternExpr.getLeftVertex();
            destVertex = edgePatternExpr.getRightVertex();

        } else { // edgeDescriptor.getEdgeDirection() == EdgeDescriptor.EdgeDirection.RIGHT_TO_LEFT
            sourceVertex = edgePatternExpr.getRightVertex();
            destVertex = edgePatternExpr.getLeftVertex();
        }

        // Collect information about our source vertex.
        VertexIdentifier sourceIdentifier = sourceVertex.generateIdentifiers(graphIdentifier).get(0);
        ElementBodyAnalysisContext sourceBodyAnalysisContext = analysisContextMap.get(sourceIdentifier);
        VariableExpr sourceVertexVariable = sourceVertex.getVariableExpr();
        List<List<String>> sourceVertexKey = elementLookupTable.getVertexKey(sourceIdentifier);
        Function<EdgeIdentifier, List<List<String>>> sourceKey = elementLookupTable::getEdgeSourceKey;
        boolean isSourceInline = sourceBodyAnalysisContext.isExpressionInline() && environment.isInlineLegal();
        boolean isSourceIntroduced = aliasLookupTable.getIterationAlias(sourceVertexVariable) != null;

        // ...and our destination vertex...
        VertexIdentifier destIdentifier = destVertex.generateIdentifiers(graphIdentifier).get(0);
        ElementBodyAnalysisContext destBodyAnalysisContext = analysisContextMap.get(destIdentifier);
        VariableExpr destVertexVariable = destVertex.getVariableExpr();
        List<List<String>> destVertexKey = elementLookupTable.getVertexKey(destIdentifier);
        Function<EdgeIdentifier, List<List<String>>> destKey = elementLookupTable::getEdgeDestKey;
        boolean isDestInline = destBodyAnalysisContext.isExpressionInline() && environment.isInlineLegal();
        boolean isDestIntroduced = aliasLookupTable.getIterationAlias(destVertexVariable) != null;

        // ...and our edge.
        List<List<String>> sourceEdgeKey = elementLookupTable.getEdgeSourceKey(edgeIdentifier);
        List<List<String>> destEdgeKey = elementLookupTable.getEdgeDestKey(edgeIdentifier);
        String sourceBodyDatasetName = sourceBodyAnalysisContext.getDatasetName();
        String destBodyDatasetName = destBodyAnalysisContext.getDatasetName();
        boolean isEdgeInline = edgeBodyAnalysisContext.isExpressionInline() && environment.isInlineLegal();
        boolean isSourceFolded = isSourceInline && sourceBodyDatasetName.equals(edgeDatasetName)
                && sourceBodyAnalysisContext.getDataverseName().equals(edgeDataverseName)
                && sourceVertexKey.equals(sourceEdgeKey);
        boolean isDestFolded = isDestInline && destBodyDatasetName.equals(edgeDatasetName)
                && destBodyAnalysisContext.getDataverseName().equals(edgeDataverseName)
                && destVertexKey.equals(destEdgeKey);

        // Condition our strategy on which vertices are currently introduced.
        if (isEdgeInline && isSourceFolded) {
            if (!isSourceIntroduced) {
                environment.acceptAction(actionFactory.buildDanglingVertexAction(sourceVertex));
            }
            environment.acceptAction(actionFactory.buildFoldedEdgeAction(sourceVertex, edgePatternExpr));
            environment.acceptAction(
                    !isDestIntroduced ? actionFactory.buildBoundVertexAction(destVertex, edgePatternExpr, destKey)
                            : actionFactory.buildRawJoinVertexAction(destVertex, edgePatternExpr, destKey));

        } else if (isEdgeInline && isDestFolded) {
            if (!isDestIntroduced) {
                environment.acceptAction(actionFactory.buildDanglingVertexAction(destVertex));
            }
            environment.acceptAction(actionFactory.buildFoldedEdgeAction(destVertex, edgePatternExpr));
            environment.acceptAction(
                    !isSourceIntroduced ? actionFactory.buildBoundVertexAction(sourceVertex, edgePatternExpr, sourceKey)
                            : actionFactory.buildRawJoinVertexAction(sourceVertex, edgePatternExpr, sourceKey));

        } else if (isSourceIntroduced && isDestIntroduced) {
            environment.acceptAction(actionFactory.buildNonFoldedEdgeAction(sourceVertex, edgePatternExpr, sourceKey));
            environment.acceptAction(actionFactory.buildRawJoinVertexAction(destVertex, edgePatternExpr, destKey));

        } else if (isSourceIntroduced) { // !isDestIntroduced
            environment.acceptAction(actionFactory.buildNonFoldedEdgeAction(sourceVertex, edgePatternExpr, sourceKey));
            environment.acceptAction(actionFactory.buildBoundVertexAction(destVertex, edgePatternExpr, destKey));

        } else if (isDestIntroduced) { // !isSourceIntroduced
            environment.acceptAction(actionFactory.buildNonFoldedEdgeAction(destVertex, edgePatternExpr, destKey));
            environment.acceptAction(actionFactory.buildBoundVertexAction(sourceVertex, edgePatternExpr, sourceKey));

        } else { // !isSourceIntroduced && !isDestIntroduced
            // When nothing is introduced, start off from LEFT to RIGHT instead of considering our source and dest.
            VertexPatternExpr leftVertex = edgePatternExpr.getLeftVertex();
            VertexPatternExpr rightVertex = edgePatternExpr.getRightVertex();
            Function<EdgeIdentifier, List<List<String>>> leftKey;
            Function<EdgeIdentifier, List<List<String>>> rightKey;
            if (edgeDescriptor.getEdgeDirection() == EdgeDescriptor.EdgeDirection.LEFT_TO_RIGHT) {
                leftKey = sourceKey;
                rightKey = destKey;

            } else { // edgeDescriptor.getEdgeDirection() == EdgeDescriptor.EdgeDirection.RIGHT_TO_LEFT
                leftKey = destKey;
                rightKey = sourceKey;
            }
            environment.acceptAction(actionFactory.buildDanglingVertexAction(leftVertex));
            environment.acceptAction(actionFactory.buildNonFoldedEdgeAction(leftVertex, edgePatternExpr, leftKey));
            environment.acceptAction(actionFactory.buildBoundVertexAction(rightVertex, edgePatternExpr, rightKey));
        }
    }