package org.vertexium.cypher.functions.list;
import org.vertexium.VertexiumException;
import org.vertexium.cypher.VertexiumCypherQueryContext;
import org.vertexium.cypher.ast.model.CypherAstBase;
import org.vertexium.cypher.exceptions.VertexiumCypherArgumentErrorException;
import org.vertexium.cypher.executor.ExpressionScope;
import org.vertexium.cypher.functions.CypherFunction;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class RangeFunction extends CypherFunction {
@Override
public Object invoke(VertexiumCypherQueryContext ctx, CypherAstBase[] arguments, ExpressionScope scope) {
if (arguments.length > 3) {
throw new VertexiumException("range function takes 2 or 3 arguments");
}
int arg0 = argumentToInt(ctx.getExpressionExecutor().executeExpression(ctx, arguments[0], scope));
int arg1 = argumentToInt(ctx.getExpressionExecutor().executeExpression(ctx, arguments[1], scope));
Stream<Integer> result = IntStream.rangeClosed(arg0, arg1).boxed();
if (arguments.length == 3) {
int step = argumentToInt(ctx.getExpressionExecutor().executeExpression(ctx, arguments[2], scope));
if (step == 0) {
throw new VertexiumCypherArgumentErrorException("NumberOutOfRange: step must be greater than 0");
}
result = result.filter(i -> i % step == 0);
}
return result;
}
private int argumentToInt(Object argument) {
if (argument instanceof Long) {
return (int) ((long) argument);
}
if (argument instanceof Integer) {
return (int) argument;
}
throw new VertexiumException("Could not convert argument \"" + argument + "\" to int");
}
}