/src/main/java/org/apache/camel/language/simple/ast/BinaryExpression.java
Java | 238 lines | 181 code | 30 blank | 27 comment | 59 complexity | 4dbcc64eaceb8ffbedb0be8a0c3702c4 MD5 | raw file
- /**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.apache.camel.language.simple.ast;
- import java.util.ArrayList;
- import java.util.Iterator;
- import java.util.List;
- import java.util.regex.Matcher;
- import java.util.regex.Pattern;
- import org.apache.camel.Exchange;
- import org.apache.camel.Expression;
- import org.apache.camel.Predicate;
- import org.apache.camel.builder.ExpressionBuilder;
- import org.apache.camel.builder.PredicateBuilder;
- import org.apache.camel.builder.ValueBuilder;
- import org.apache.camel.language.simple.BinaryOperatorType;
- import org.apache.camel.language.simple.SimpleIllegalSyntaxException;
- import org.apache.camel.language.simple.SimpleParserException;
- import org.apache.camel.language.simple.SimpleToken;
- import org.apache.camel.util.ObjectHelper;
- /**
- * Represents a binary expression in the AST.
- */
- public class BinaryExpression extends BaseSimpleNode {
- // this is special for the range operator where you define the range as from..to (where from and to are numbers)
- private static final Pattern RANGE_PATTERN = Pattern.compile("^(\\d+)(\\.\\.)(\\d+)$");
- private final BinaryOperatorType operator;
- private SimpleNode left;
- private SimpleNode right;
- public BinaryExpression(SimpleToken token) {
- super(token);
- operator = BinaryOperatorType.asOperator(token.getText());
- }
- @Override
- public String toString() {
- return left + " " + token.getText() + " " + right;
- }
- public boolean acceptLeftNode(SimpleNode lef) {
- this.left = lef;
- return true;
- }
- public boolean acceptRightNode(SimpleNode right) {
- this.right = right;
- return true;
- }
- public BinaryOperatorType getOperator() {
- return operator;
- }
- @Override
- public Expression createExpression(String expression) {
- ObjectHelper.notNull(left, "left node", this);
- ObjectHelper.notNull(right, "right node", this);
- final Expression leftExp = left.createExpression(expression);
- final Expression rightExp = right.createExpression(expression);
- if (operator == BinaryOperatorType.EQ) {
- return createExpression(leftExp, rightExp, PredicateBuilder.isEqualTo(leftExp, rightExp));
- } else if (operator == BinaryOperatorType.GT) {
- return createExpression(leftExp, rightExp, PredicateBuilder.isGreaterThan(leftExp, rightExp));
- } else if (operator == BinaryOperatorType.GTE) {
- return createExpression(leftExp, rightExp, PredicateBuilder.isGreaterThanOrEqualTo(leftExp, rightExp));
- } else if (operator == BinaryOperatorType.LT) {
- return createExpression(leftExp, rightExp, PredicateBuilder.isLessThan(leftExp, rightExp));
- } else if (operator == BinaryOperatorType.LTE) {
- return createExpression(leftExp, rightExp, PredicateBuilder.isLessThanOrEqualTo(leftExp, rightExp));
- } else if (operator == BinaryOperatorType.NOT_EQ) {
- return createExpression(leftExp, rightExp, PredicateBuilder.isNotEqualTo(leftExp, rightExp));
- } else if (operator == BinaryOperatorType.CONTAINS) {
- return createExpression(leftExp, rightExp, PredicateBuilder.contains(leftExp, rightExp));
- } else if (operator == BinaryOperatorType.NOT_CONTAINS) {
- return createExpression(leftExp, rightExp, PredicateBuilder.not(PredicateBuilder.contains(leftExp, rightExp)));
- } else if (operator == BinaryOperatorType.IS || operator == BinaryOperatorType.NOT_IS) {
- return createIsExpression(expression, leftExp, rightExp);
- } else if (operator == BinaryOperatorType.REGEX || operator == BinaryOperatorType.NOT_REGEX) {
- return createRegexExpression(leftExp, rightExp);
- } else if (operator == BinaryOperatorType.IN || operator == BinaryOperatorType.NOT_IN) {
- return createInExpression(leftExp, rightExp);
- } else if (operator == BinaryOperatorType.RANGE || operator == BinaryOperatorType.NOT_RANGE) {
- return createRangeExpression(expression, leftExp, rightExp);
- }
- throw new SimpleParserException("Unknown binary operator " + operator, token.getIndex());
- }
- private Expression createIsExpression(final String expression, final Expression leftExp, final Expression rightExp) {
- return new Expression() {
- @Override
- public <T> T evaluate(Exchange exchange, Class<T> type) {
- Predicate predicate;
- String name = rightExp.evaluate(exchange, String.class);
- if (name == null || "null".equals(name)) {
- throw new SimpleIllegalSyntaxException(expression, right.getToken().getIndex(), operator + " operator cannot accept null. A class type must be provided.");
- }
- Class<?> rightType = exchange.getContext().getClassResolver().resolveClass(name);
- if (rightType == null) {
- throw new SimpleIllegalSyntaxException(expression, right.getToken().getIndex(), operator + " operator cannot find class with name: " + name);
- }
- predicate = PredicateBuilder.isInstanceOf(leftExp, rightType);
- if (operator == BinaryOperatorType.NOT_IS) {
- predicate = PredicateBuilder.not(predicate);
- }
- boolean answer = predicate.matches(exchange);
- return exchange.getContext().getTypeConverter().convertTo(type, answer);
- }
- @Override
- public String toString() {
- return left + " " + token.getText() + " " + right;
- }
- };
- }
- private Expression createRegexExpression(final Expression leftExp, final Expression rightExp) {
- return new Expression() {
- @Override
- public <T> T evaluate(Exchange exchange, Class<T> type) {
- // reg ex should use String pattern, so we evaluate the right hand side as a String
- Predicate predicate = PredicateBuilder.regex(leftExp, rightExp.evaluate(exchange, String.class));
- if (operator == BinaryOperatorType.NOT_REGEX) {
- predicate = PredicateBuilder.not(predicate);
- }
- boolean answer = predicate.matches(exchange);
- return exchange.getContext().getTypeConverter().convertTo(type, answer);
- }
- @Override
- public String toString() {
- return left + " " + token.getText() + " " + right;
- }
- };
- }
- private Expression createInExpression(final Expression leftExp, final Expression rightExp) {
- return new Expression() {
- @Override
- public <T> T evaluate(Exchange exchange, Class<T> type) {
- // okay the in operator is a bit more complex as we need to build a list of values
- // from the right hand side expression.
- // each element on the right hand side must be separated by comma (default for create iterator)
- Iterator<Object> it = ObjectHelper.createIterator(rightExp.evaluate(exchange, Object.class));
- List<Object> values = new ArrayList<Object>();
- while (it.hasNext()) {
- values.add(it.next());
- }
- // then reuse value builder to create the in predicate with the list of values
- ValueBuilder vb = new ValueBuilder(leftExp);
- Predicate predicate = vb.in(values.toArray());
- if (operator == BinaryOperatorType.NOT_IN) {
- predicate = PredicateBuilder.not(predicate);
- }
- boolean answer = predicate.matches(exchange);
- return exchange.getContext().getTypeConverter().convertTo(type, answer);
- }
- @Override
- public String toString() {
- return left + " " + token.getText() + " " + right;
- }
- };
- }
- private Expression createRangeExpression(final String expression, final Expression leftExp, final Expression rightExp) {
- return new Expression() {
- @Override
- public <T> T evaluate(Exchange exchange, Class<T> type) {
- Predicate predicate;
- String range = rightExp.evaluate(exchange, String.class);
- Matcher matcher = RANGE_PATTERN.matcher(range);
- if (matcher.matches()) {
- // wrap as constant expression for the from and to values
- Expression from = ExpressionBuilder.constantExpression(matcher.group(1));
- Expression to = ExpressionBuilder.constantExpression(matcher.group(3));
- // build a compound predicate for the range
- predicate = PredicateBuilder.isGreaterThanOrEqualTo(leftExp, from);
- predicate = PredicateBuilder.and(predicate, PredicateBuilder.isLessThanOrEqualTo(leftExp, to));
- } else {
- throw new SimpleIllegalSyntaxException(expression, right.getToken().getIndex(), operator + " operator is not valid. Valid syntax:'from..to' (where from and to are numbers).");
- }
- if (operator == BinaryOperatorType.NOT_RANGE) {
- predicate = PredicateBuilder.not(predicate);
- }
- boolean answer = predicate.matches(exchange);
- return exchange.getContext().getTypeConverter().convertTo(type, answer);
- }
- @Override
- public String toString() {
- return left + " " + token.getText() + " " + right;
- }
- };
- }
- private Expression createExpression(final Expression left, final Expression right, final Predicate predicate) {
- return new Expression() {
- @Override
- public <T> T evaluate(Exchange exchange, Class<T> type) {
- boolean answer = predicate.matches(exchange);
- return exchange.getContext().getTypeConverter().convertTo(type, answer);
- }
- @Override
- public String toString() {
- return left + " " + token.getText() + " " + right;
- }
- };
- }
- }