@Override public int _handleToken(ParseContext ctx) throws InvalidQueryException { Token token = ctx.getTokens()[ctx.getCurrentTokensIndex()]; ctx.getPrecedingExpression().setLeftOperand(token.getValue()); return 1; }
/** * Generate a Predicate instance from an array of tokens. Each input token contains a type and a * value. * * <p>Based on the token type and location, the tokens are first translated into a list of * expressions, both relational and logical. These expressions are then merged into a tree of * expressions with a single root following operator precedence and explicit grouping rules. * Depending on the query, this merging of expressions into a tree of expressions may occur in * several passes, one pass per level of precedence starting at the highest level of precedence. * * <p>The predicate is built by traversing the expression tree in-order with each node expressing * itself as a predicate. * * @param tokens an array of tokens which represent the query, each token contains type and value * information * @return a new predicate instance based on the supplied tokens * @throws InvalidQueryException if unable to parse the tokens and produce a predicate */ public Predicate parse(Token[] tokens) throws InvalidQueryException { ParseContext ctx = parseExpressions(tokens); List<Expression> listExpressions = ctx.getExpressions(); List<Expression> listMergedExpressions = mergeExpressions(listExpressions, ctx.getMaxPrecedence()); return listMergedExpressions.isEmpty() ? null : listMergedExpressions.get(0).toPredicate(); }
@Override public int _handleToken(ParseContext ctx) throws InvalidQueryException { Token token = ctx.getTokens()[ctx.getCurrentTokensIndex()]; RelationalOperator relationalOp = RelationalOperatorFactory.createOperator(token.getValue()); // todo: use factory to create expression ctx.addExpression(new RelationalExpression(relationalOp)); return 1; }
@Override public int _handleToken(ParseContext ctx) throws InvalidQueryException { Token token = ctx.getTokens()[ctx.getCurrentTokensIndex()]; LogicalOperator logicalOp = LogicalOperatorFactory.createOperator(token.getValue(), ctx.getPrecedenceLevel()); ctx.updateMaxPrecedence(logicalOp.getPrecedence()); ctx.addExpression(LogicalExpressionFactory.createLogicalExpression(logicalOp)); return 1; }
/** * Create parse context from an array of tokens. The parse context contains a list of expressions * and other information about the expressions an parsed tokens. * * @param tokens an array of tokens which represent the query, each token contains type and value * information * @return a parse context which contains a list of expressions * @throws InvalidQueryException if unable to properly parse the tokens into a parse context */ private ParseContext parseExpressions(Token[] tokens) throws InvalidQueryException { ParseContext ctx = new ParseContext(tokens); while (ctx.getCurrentTokensIndex() < tokens.length) { TOKEN_HANDLERS.get(tokens[ctx.getCurrentTokensIndex()].getType()).handleToken(ctx); } if (ctx.getPrecedenceLevel() != 0) { throw new InvalidQueryException("Invalid query string: mismatched parentheses."); } return ctx; }
@Override public int _handleToken(ParseContext ctx) throws InvalidQueryException { Token[] tokens = ctx.getTokens(); int idx = ctx.getCurrentTokensIndex(); Token token = tokens[idx]; RelationalOperator relationalOp = RelationalOperatorFactory.createOperator(token.getValue()); ctx.addExpression(new RelationalExpression(relationalOp)); ctx.setCurrentTokensIndex(++idx); TokenHandler propertyHandler = new PropertyOperandTokenHandler(); propertyHandler.handleToken(ctx); // handle right operand if applicable to operator idx = ctx.getCurrentTokensIndex(); if (ctx.getCurrentTokensIndex() < tokens.length && tokens[idx].getType().equals(Token.TYPE.VALUE_OPERAND)) { TokenHandler valueHandler = new ValueOperandTokenHandler(); valueHandler.handleToken(ctx); } // skip closing bracket idx = ctx.getCurrentTokensIndex(); if (idx >= tokens.length || tokens[idx].getType() != Token.TYPE.BRACKET_CLOSE) { throw new InvalidQueryException("Missing closing bracket for in expression."); } return 1; }
/** * Process a token. Handles common token processing functionality then delegates to the * individual concrete handlers. * * @param ctx the current parse context * @throws InvalidQueryException if unable to process the token */ public void handleToken(ParseContext ctx) throws InvalidQueryException { Token token = ctx.getTokens()[ctx.getCurrentTokensIndex()]; if (!validate(ctx.getPreviousTokenType())) { throw new InvalidQueryException( "Unexpected token encountered in query string. Last Token Type=" + ctx.getPreviousTokenType() + ", Current Token[type=" + token.getType() + ", value='" + token.getValue() + "']"); } ctx.setTokenType(token.getType()); int idxIncrement = _handleToken(ctx); ctx.setCurrentTokensIndex(ctx.getCurrentTokensIndex() + idxIncrement); }
@Override public int _handleToken(ParseContext ctx) throws InvalidQueryException { ctx.decPrecedenceLevel(Operator.MAX_OP_PRECEDENCE); return 1; }
@Override public int _handleToken(ParseContext ctx) { ctx.incPrecedenceLevel(Operator.MAX_OP_PRECEDENCE); return 1; }