package com.avaje.ebeaninternal.server.grammer; import com.avaje.ebean.ExpressionList; import com.avaje.ebean.Query; import com.avaje.ebeaninternal.server.grammer.antlr.EQLBaseListener; import com.avaje.ebeaninternal.server.grammer.antlr.EQLLexer; import com.avaje.ebeaninternal.server.grammer.antlr.EQLParser; import com.avaje.ebeaninternal.server.util.ArrayStack; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.TerminalNode; class EqlAdapter extends EQLBaseListener { private static final OperatorMapping operatorMapping = new OperatorMapping(); private final Query query; private final EqlAdapterHelper helper; private ArrayStack> textStack; private ArrayStack> whereStack; private boolean textMode; public EqlAdapter(Query query) { this.query = query; this.helper = new EqlAdapterHelper(this); } /** * Return the current expression list that expressions should be added to. */ protected ExpressionList peekExprList() { if (textMode) { // return the current text expression list return _peekText(); } if (whereStack == null) { whereStack = new ArrayStack>(); whereStack.push(query.where()); } // return the current expression list return whereStack.peek(); } private ExpressionList _peekText() { if (textStack == null) { textStack = new ArrayStack>(); // empty so push on the queries base expression list textStack.push(query.text()); } // return the current expression list return textStack.peek(); } /** * Push the expression list onto the appropriate stack. */ private void pushExprList(ExpressionList list, String type) { System.out.println("Push " + type + ">> "); if (textMode) { textStack.push(list); } else { whereStack.push(list); } } /** * End a list of expressions added by 'OR'. */ private void popJunction(String type) { System.out.println("Pop " + type + " >> "); if (textMode) { textStack.pop(); } else { whereStack.pop(); } } private String getLeftHandSidePath(ParserRuleContext ctx) { TerminalNode pathToken = ctx.getToken(EQLLexer.PATH_VARIABLE, 0); return pathToken.getText(); } @Override public void enterBetween_expression(EQLParser.Between_expressionContext ctx) { } @Override public void enterPropertyBetween_expression(EQLParser.PropertyBetween_expressionContext ctx) { } @Override public void enterIn_expression(EQLParser.In_expressionContext ctx) { } @Override public void enterIsNull_expression(EQLParser.IsNull_expressionContext ctx) { String path = getLeftHandSidePath(ctx); peekExprList().isNull(path); } @Override public void enterIsNotNull_expression(EQLParser.IsNotNull_expressionContext ctx) { String path = getLeftHandSidePath(ctx); peekExprList().isNotNull(path); } @Override public void enterIsEmpty_expression(EQLParser.IsEmpty_expressionContext ctx) { String path = getLeftHandSidePath(ctx); peekExprList().isEmpty(path); } @Override public void enterIsNotEmpty_expression(EQLParser.IsNotEmpty_expressionContext ctx) { String path = getLeftHandSidePath(ctx); peekExprList().isNotEmpty(path); } @Override public void enterLike_expression(EQLParser.Like_expressionContext ctx) { addExpression(ctx); } @Override public void enterComparison_expression(EQLParser.Comparison_expressionContext ctx) { addExpression(ctx); } private void addExpression(ParserRuleContext ctx) { int childCount = ctx.getChildCount(); if (childCount < 3) { throw new IllegalStateException("expecting 3 children for comparison? " + ctx); } String path = getLeftHandSidePath(ctx); String operator = ctx.getChild(1).getText(); EqlOperator op = operatorMapping.get(operator); if (op == null) { throw new IllegalStateException("No operator found for " + op); } // RHS is Path, Literal or Named input parameter ParseTree rhs = ctx.getChild(2); helper.addExpression(path, op, rhs.getText()); } @Override public void enterConditional_term(EQLParser.Conditional_termContext ctx) { int childCount = ctx.getChildCount(); if (childCount > 1) { pushExprList(peekExprList().and(), "Conjunction"); } } @Override public void exitConditional_term(EQLParser.Conditional_termContext ctx) { if (ctx.getChildCount() > 1) { popJunction("Conjunction"); } } @Override public void enterConditional_expression(EQLParser.Conditional_expressionContext ctx) { if (ctx.getChildCount() > 1) { pushExprList(peekExprList().or(), "Disjunction"); } } @Override public void exitConditional_expression(EQLParser.Conditional_expressionContext ctx) { if (ctx.getChildCount() > 1) { popJunction("Disjunction"); } } @Override public void enterConditional_factor(EQLParser.Conditional_factorContext ctx) { if (ctx.getChildCount() > 1) { pushExprList(peekExprList().not(), "Not"); } } @Override public void exitConditional_factor(EQLParser.Conditional_factorContext ctx) { if (ctx.getChildCount() > 1) { popJunction("Not"); } } }