package org.vertexium.cypher.executor; import org.vertexium.VertexiumException; import org.vertexium.cypher.VertexiumCypherQueryContext; import org.vertexium.cypher.VertexiumCypherScope; import org.vertexium.cypher.ast.model.CypherUnwindClause; import org.vertexium.util.VertexiumLogger; import org.vertexium.util.VertexiumLoggerFactory; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; public class UnwindClauseExecutor { private static final VertexiumLogger LOGGER = VertexiumLoggerFactory.getLogger(UnwindClauseExecutor.class); private final ExpressionExecutor expressionExecutor; public UnwindClauseExecutor(ExpressionExecutor expressionExecutor) { this.expressionExecutor = expressionExecutor; } public VertexiumCypherScope execute(VertexiumCypherQueryContext ctx, List<CypherUnwindClause> clauses, VertexiumCypherScope scope) { List<VertexiumCypherScope> allResults = new ArrayList<>(); VertexiumCypherScope accumulatorScope = scope; for (CypherUnwindClause clause : clauses) { List<VertexiumCypherScope.Item> clauseResults = new ArrayList<>(); accumulatorScope.stream().forEach(item -> { List<VertexiumCypherScope.Item> items = execute(ctx, clause, item).collect(Collectors.toList()); clauseResults.addAll(items); }); accumulatorScope = VertexiumCypherScope.newItemsScope(clauseResults, scope); allResults.add(accumulatorScope); } return accumulatorScope; } private Stream<VertexiumCypherScope.Item> execute(VertexiumCypherQueryContext ctx, CypherUnwindClause clause, ExpressionScope scope) { LOGGER.debug("execute: %s", clause); Object exprResult = expressionExecutor.executeExpression(ctx, clause.getExpression(), scope); Stream<?> stream; if (exprResult == null) { return Stream.of(); } else if (exprResult instanceof Stream) { stream = (Stream<?>) exprResult; } else if (exprResult instanceof Collection) { Collection<?> collection = (Collection<?>) exprResult; stream = collection.stream(); } else { throw new VertexiumException("unhandled data type: " + exprResult.getClass().getName()); } return stream .map(o -> VertexiumCypherScope.newMapItem(clause.getName(), o, scope)); } }