/*
 * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.javafx.fxml.expression;

import java.io.IOException;
import java.io.PushbackReader;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.sun.javafx.fxml.BeanAdapter;
import static com.sun.javafx.fxml.expression.Operator.*;

Abstract base class for expressions. Also provides static methods for creating arithmetic and logical expressions as well as accessing namespace values by key path.
/** * Abstract base class for expressions. Also provides static methods for * creating arithmetic and logical expressions as well as accessing namespace * values by key path. */
public abstract class Expression<T> { // Expression parser class private static class Parser { public static class Token { public Token(TokenType type, Object value) { this.type = type; this.value = value; } public final TokenType type; public final Object value; @Override public String toString() { return value.toString(); } } public enum TokenType { LITERAL, VARIABLE, FUNCTION, UNARY_OPERATOR, BINARY_OPERATOR, BEGIN_GROUP, END_GROUP } private int c = -1; private char[] pushbackBuffer = new char[PUSHBACK_BUFFER_SIZE]; private static final int PUSHBACK_BUFFER_SIZE = 6; public Expression parse(Reader reader) throws IOException { LinkedList<Token> tokens = tokenize(new PushbackReader(reader, PUSHBACK_BUFFER_SIZE)); LinkedList<Expression> stack = new LinkedList<Expression>(); for (Token token : tokens) { Expression<?> expression; switch (token.type) { case LITERAL: { expression = new LiteralExpression(token.value); break; } case VARIABLE: { expression = new VariableExpression((KeyPath)token.value); break; } case FUNCTION: { // TODO Create a new FunctionExpression type; this // class will have a property of type Method that // refers to a method defined by the "scope context" // (e.g. an FXML document controller), which must be // set prior to evaluating the expression; it will // also have a list of argument Expressions expression = null; break; } case UNARY_OPERATOR: { Operator operator = (Operator)token.value; Expression operand = stack.pop(); switch(operator) { case NEGATE: expression = negate(operand); break; case NOT: expression = not(operand); break; default: throw new UnsupportedOperationException(); } break; } case BINARY_OPERATOR: { Operator operator = (Operator)token.value; Expression right = stack.pop(); Expression left = stack.pop(); switch(operator) { case ADD: expression = add(left, right); break; case SUBTRACT: expression = subtract(left, right); break; case MULTIPLY: expression = multiply(left, right); break; case DIVIDE: expression = divide(left, right); break; case MODULO: expression = modulo(left, right); break; case GREATER_THAN: expression = greaterThan(left, right); break; case GREATER_THAN_OR_EQUAL_TO: expression = greaterThanOrEqualTo(left, right); break; case LESS_THAN: expression = lessThan(left, right); break; case LESS_THAN_OR_EQUAL_TO: expression = lessThanOrEqualTo(left, right); break; case EQUAL_TO: expression = equalTo(left, right); break; case NOT_EQUAL_TO: expression = notEqualTo(left, right); break; case AND: expression = and(left, right); break; case OR: expression = or(left, right); break; default: throw new UnsupportedOperationException(); } break; } default: { throw new UnsupportedOperationException(); } } stack.push(expression); } if (stack.size() != 1) { throw new IllegalArgumentException("Invalid expression."); } return stack.peek(); } private LinkedList<Token> tokenize(PushbackReader reader) throws IOException { // Read the string into a postfix list of tokens LinkedList<Token> tokens = new LinkedList<Token>(); LinkedList<Token> stack = new LinkedList<Token>(); c = reader.read(); boolean unary = true; while (c != -1) { // Skip whitespace while (c != -1 && Character.isWhitespace(c)) { c = reader.read(); } if (c != -1) { Token token; if (c == 'n') { if (readKeyword(reader, NULL_KEYWORD)) { token = new Token(TokenType.LITERAL, null); } else { token = new Token(TokenType.VARIABLE, KeyPath.parse(reader)); c = reader.read(); } } else if (c == '"' || c == '\'') { StringBuilder stringBuilder = new StringBuilder(); // Use the same delimiter to close the string int t = c; // Move to the next character after the delimiter c = reader.read(); while (c != -1 && c != t) { if (!Character.isISOControl(c)) { if (c == '\\') { c = reader.read(); if (c == 'b') { c = '\b'; } else if (c == 'f') { c = '\f'; } else if (c == 'n') { c = '\n'; } else if (c == 'r') { c = '\r'; } else if (c == 't') { c = '\t'; } else if (c == 'u') { StringBuilder unicodeValueBuilder = new StringBuilder(); while (unicodeValueBuilder.length() < 4) { c = reader.read(); unicodeValueBuilder.append((char)c); } String unicodeValue = unicodeValueBuilder.toString(); c = (char)Integer.parseInt(unicodeValue, 16); } else { if (!(c == '\\' || c == '/' || c == '\"' || c == '\'' || c == t)) { throw new IllegalArgumentException("Unsupported escape sequence."); } } } stringBuilder.append((char)c); } c = reader.read(); } if (c != t) { throw new IllegalArgumentException("Unterminated string."); } // Move to the next character after the delimiter c = reader.read(); token = new Token(TokenType.LITERAL, stringBuilder.toString()); } else if (Character.isDigit(c)) { StringBuilder numberBuilder = new StringBuilder(); boolean integer = true; while (c != -1 && (Character.isDigit(c) || c == '.' || c == 'e' || c == 'E')) { numberBuilder.append((char)c); integer &= !(c == '.'); c = reader.read(); } Number value; if (integer) { value = Long.parseLong(numberBuilder.toString()); } else { value = Double.parseDouble(numberBuilder.toString()); } token = new Token(TokenType.LITERAL, value); } else if (c == 't') { if (readKeyword(reader, TRUE_KEYWORD)) { token = new Token(TokenType.LITERAL, true); } else { token = new Token(TokenType.VARIABLE, KeyPath.parse(reader)); c = reader.read(); } } else if (c == 'f') { if (readKeyword(reader, FALSE_KEYWORD)) { token = new Token(TokenType.LITERAL, false); } else { token = new Token(TokenType.VARIABLE, KeyPath.parse(reader)); c = reader.read(); } } else if (Character.isJavaIdentifierStart(c)) { reader.unread(c); // TODO Here (and everywhere else where we call KeyPath.parse()), // read the path value. If c == '(' when this method returns, the // path refers to a function; read the arguments and create a // FUNCTION token token = new Token(TokenType.VARIABLE, KeyPath.parse(reader)); c = reader.read(); } else { boolean readNext = true; if (unary) { switch(c) { case '-': token = new Token(TokenType.UNARY_OPERATOR, NEGATE); break; case '!': token = new Token(TokenType.UNARY_OPERATOR, NOT); break; case '(': token = new Token(TokenType.BEGIN_GROUP, null); break; default: throw new IllegalArgumentException("Unexpected character in expression."); } } else { switch(c) { case '+': token = new Token(TokenType.BINARY_OPERATOR, ADD); break; case '-': token = new Token(TokenType.BINARY_OPERATOR, SUBTRACT); break; case '*': token = new Token(TokenType.BINARY_OPERATOR, MULTIPLY); break; case '/': token = new Token(TokenType.BINARY_OPERATOR, DIVIDE); break; case '%': token = new Token(TokenType.BINARY_OPERATOR, MODULO); break; case '=': c = reader.read(); if (c == '=') { token = new Token(TokenType.BINARY_OPERATOR, EQUAL_TO); } else { throw new IllegalArgumentException("Unexpected character in expression."); } break; case '!': c = reader.read(); if (c == '=') { token = new Token(TokenType.BINARY_OPERATOR, NOT_EQUAL_TO); } else { throw new IllegalArgumentException("Unexpected character in expression."); } break; case '>': c = reader.read(); if (c == '=') { token = new Token(TokenType.BINARY_OPERATOR, GREATER_THAN_OR_EQUAL_TO); } else { readNext = false; token = new Token(TokenType.BINARY_OPERATOR, GREATER_THAN); } break; case '<': c = reader.read(); if (c == '=') { token = new Token(TokenType.BINARY_OPERATOR, LESS_THAN_OR_EQUAL_TO); } else { readNext = false; token = new Token(TokenType.BINARY_OPERATOR, LESS_THAN); } break; case '&': c = reader.read(); if (c == '&') { token = new Token(TokenType.BINARY_OPERATOR, AND); } else { throw new IllegalArgumentException("Unexpected character in expression."); } break; case '|': c = reader.read(); if (c == '|') { token = new Token(TokenType.BINARY_OPERATOR, OR); } else { throw new IllegalArgumentException("Unexpected character in expression."); } break; case ')': token = new Token(TokenType.END_GROUP, null); break; default: throw new IllegalArgumentException("Unexpected character in expression."); } } if (readNext) { c = reader.read(); } } // Process the token switch (token.type) { case LITERAL: case VARIABLE: { tokens.add(token); break; } case UNARY_OPERATOR: case BINARY_OPERATOR: { int priority = ((Operator)token.value).getPriority(); while (!stack.isEmpty() && stack.peek().type != TokenType.BEGIN_GROUP && ((Operator)stack.peek().value).getPriority() >= priority && ((Operator)stack.peek().value).getPriority() != Operator.MAX_PRIORITY) { tokens.add(stack.pop()); } stack.push(token); break; } case BEGIN_GROUP: { stack.push(token); break; } case END_GROUP: { for (Token t = stack.pop(); t.type != TokenType.BEGIN_GROUP; t = stack.pop()) { tokens.add(t); } break; } default: { throw new UnsupportedOperationException(); } } unary = !(token.type == TokenType.LITERAL || token.type == TokenType.VARIABLE || token.type == TokenType.END_GROUP); } } while (!stack.isEmpty()) { tokens.add(stack.pop()); } return tokens; } private boolean readKeyword(PushbackReader reader, String keyword) throws IOException { int n = keyword.length(); int i = 0; while (c != -1 && i < n) { pushbackBuffer[i] = (char)c; if (keyword.charAt(i) != c) { break; } c = reader.read(); i++; } boolean result; if (i < n) { reader.unread(pushbackBuffer, 0, i + 1); result = false; } else { result = true; } return result; } } private static final String NULL_KEYWORD = "null"; private static final String TRUE_KEYWORD = "true"; private static final String FALSE_KEYWORD = "false";
Evaluates the expression.
Params:
  • namespace – The namespace against which the expression will be evaluated.
Returns: The result of evaluating the expression.
/** * Evaluates the expression. * * @param namespace * The namespace against which the expression will be evaluated. * * @return * The result of evaluating the expression. */
public abstract T evaluate(Object namespace);
Updates the expression value.
Params:
  • namespace – The namespace against which the expression will be evaluated.
  • value – The value to assign to the expression.
/** * Updates the expression value. * * @param namespace * The namespace against which the expression will be evaluated. * * @param value * The value to assign to the expression. */
public abstract void update(Object namespace, T value);
Tests whether the expression is defined.
Params:
  • namespace – The namespace against which the expression will be evaluated.
Returns: true if the expression is defined; false, otherwise.
/** * Tests whether the expression is defined. * * @param namespace * The namespace against which the expression will be evaluated. * * @return * <tt>true</tt> if the expression is defined; <tt>false</tt>, otherwise. */
public abstract boolean isDefined(Object namespace);
Tests whether the expression represents an l-value (i.e. can be assigned to).
Returns: true if the expression is an l-value; false, otherwise.
/** * Tests whether the expression represents an l-value (i.e. can be * assigned to). * * @return * <tt>true</tt> if the expression is an l-value; <tt>false</tt>, * otherwise. */
public abstract boolean isLValue();
Returns a list of arguments to this expression.
/** * Returns a list of arguments to this expression. */
public List<KeyPath> getArguments() { ArrayList<KeyPath> arguments = new ArrayList<KeyPath>(); getArguments(arguments); return arguments; }
Populates a list of arguments to this expression.
/** * Populates a list of arguments to this expression. */
protected abstract void getArguments(List<KeyPath> arguments);
Returns the value at a given path within a namespace.
Params:
  • namespace –
  • keyPath –
Returns: The value at the given path, or null if no such value exists.
/** * Returns the value at a given path within a namespace. * * @param namespace * @param keyPath * * @return * The value at the given path, or <tt>null</tt> if no such value exists. */
@SuppressWarnings("unchecked") public static <T> T get(Object namespace, KeyPath keyPath) { if (keyPath == null) { throw new NullPointerException(); } return (T)get(namespace, keyPath.iterator()); }
Returns the value at a given path within a namespace.
Params:
  • namespace –
  • keyPathIterator –
Returns: The value at the given path, or null if no such value exists.
/** * Returns the value at a given path within a namespace. * * @param namespace * @param keyPathIterator * * @return * The value at the given path, or <tt>null</tt> if no such value exists. */
@SuppressWarnings("unchecked") private static <T> T get(Object namespace, Iterator<String> keyPathIterator) { if (keyPathIterator == null) { throw new NullPointerException(); } T value; if (keyPathIterator.hasNext()) { // TODO Remove cast to T when build is updated to Java 7 value = (T)get(get(namespace, keyPathIterator.next()), keyPathIterator); } else { value = (T)namespace; } return value; }
Returns the value at a given key within a namespace.
Params:
  • namespace –
  • key –
Returns: The value at the given key, or null if no such value exists.
/** * Returns the value at a given key within a namespace. * * @param namespace * @param key * * @return * The value at the given key, or <tt>null</tt> if no such value exists. */
@SuppressWarnings("unchecked") public static <T> T get(Object namespace, String key) { if (key == null) { throw new NullPointerException(); } Object value; if (namespace instanceof List<?>) { List<Object> list = (List<Object>)namespace; value = list.get(Integer.parseInt(key)); } else if (namespace != null) { Map<String, Object> map; if (namespace instanceof Map<?, ?>) { map = (Map<String, Object>)namespace; } else { map = new BeanAdapter(namespace); } value = map.get(key); } else { value = null; } return (T)value; }
Sets the value at a given path within a namespace.
Params:
  • namespace –
  • keyPath –
  • value –
/** * Sets the value at a given path within a namespace. * * @param namespace * @param keyPath * @param value */
public static void set(Object namespace, KeyPath keyPath, Object value) { if (keyPath == null) { throw new NullPointerException(); } set(namespace, keyPath.iterator(), value); }
Sets the value at a given path within a namespace.
Params:
  • namespace –
  • keyPathIterator –
  • value –
/** * Sets the value at a given path within a namespace. * * @param namespace * @param keyPathIterator * @param value */
private static void set(Object namespace, Iterator<String> keyPathIterator, Object value) { if (keyPathIterator == null) { throw new NullPointerException(); } if (!keyPathIterator.hasNext()) { throw new IllegalArgumentException(); } String key = keyPathIterator.next(); if (keyPathIterator.hasNext()) { set(get(namespace, key), keyPathIterator, value); } else { set(namespace, key, value); } }
Sets the value at a given path within a namespace.
Params:
  • namespace –
  • key –
  • value –
/** * Sets the value at a given path within a namespace. * * @param namespace * @param key * @param value */
@SuppressWarnings("unchecked") public static void set(Object namespace, String key, Object value) { if (key == null) { throw new NullPointerException(); } if (namespace instanceof List<?>) { List<Object> list = (List<Object>)namespace; list.set(Integer.parseInt(key), value); } else if (namespace != null) { Map<String, Object> map; if (namespace instanceof Map<?, ?>) { map = (Map<String, Object>)namespace; } else { map = new BeanAdapter(namespace); } map.put(key, value); } else { throw new IllegalArgumentException(); } }
Tests the existence of a path within a namespace.
Params:
  • namespace –
  • keyPath –
Returns: true if the path exists; false, otherwise.
/** * Tests the existence of a path within a namespace. * * @param namespace * @param keyPath * * @return * <tt>true</tt> if the path exists; <tt>false</tt>, otherwise. */
public static boolean isDefined(Object namespace, KeyPath keyPath) { if (keyPath == null) { throw new NullPointerException(); } return isDefined(namespace, keyPath.iterator()); }
Tests the existence of a path within a namespace.
Params:
  • namespace –
  • keyPathIterator –
Returns: true if the path exists; false, otherwise.
/** * Tests the existence of a path within a namespace. * * @param namespace * @param keyPathIterator * * @return * <tt>true</tt> if the path exists; <tt>false</tt>, otherwise. */
private static boolean isDefined(Object namespace, Iterator<String> keyPathIterator) { if (keyPathIterator == null) { throw new NullPointerException(); } if (!keyPathIterator.hasNext()) { throw new IllegalArgumentException(); } String key = keyPathIterator.next(); boolean defined; if (keyPathIterator.hasNext()) { defined = isDefined(get(namespace, key), keyPathIterator); } else { defined = isDefined(namespace, key); } return defined; }
Tests the existence of a key within a namespace.
Params:
  • namespace –
  • key –
Returns: true if the key exists; false, otherwise.
/** * Tests the existence of a key within a namespace. * * @param namespace * @param key * * @return * <tt>true</tt> if the key exists; <tt>false</tt>, otherwise. */
@SuppressWarnings("unchecked") public static boolean isDefined(Object namespace, String key) { if (key == null) { throw new NullPointerException(); } boolean defined; if (namespace instanceof List<?>) { List<Object> list = (List<Object>)namespace; defined = Integer.parseInt(key) < list.size(); } else if (namespace != null) { Map<String, Object> map; if (namespace instanceof Map<?, ?>) { map = (Map<String, Object>)namespace; } else { map = new BeanAdapter(namespace); } defined = map.containsKey(key); } else { defined = false; } return defined; }
Creates an addition or concatenation expression.
Params:
  • left –
  • right –
/** * Creates an addition or concatenation expression. * * @param left * @param right */
public static BinaryExpression add(Expression left, Expression right) { return new BinaryExpression(left, right, (leftValue, rightValue) -> { Object value; if (leftValue instanceof String || rightValue instanceof String) { value = leftValue.toString().concat(rightValue.toString()); } else { Number leftNumber = (Number)leftValue; Number rightNumber = (Number)rightValue; if (leftNumber instanceof Double || rightNumber instanceof Double) { value = leftNumber.doubleValue() + rightNumber.doubleValue(); } else if (leftNumber instanceof Float || rightNumber instanceof Float) { value = leftNumber.floatValue() + rightNumber.floatValue(); } else if (leftNumber instanceof Long || rightNumber instanceof Long) { value = leftNumber.longValue() + rightNumber.longValue(); } else if (leftNumber instanceof Integer || rightNumber instanceof Integer) { value = leftNumber.intValue() + rightNumber.intValue(); } else if (leftNumber instanceof Short || rightNumber instanceof Short) { value = leftNumber.shortValue() + rightNumber.shortValue(); } else if (leftNumber instanceof Byte || rightNumber instanceof Byte) { value = leftNumber.byteValue() + rightNumber.byteValue(); } else { throw new UnsupportedOperationException(); } } return value; }); }
Creates an addition or concatenation expression.
Params:
  • left –
  • right –
/** * Creates an addition or concatenation expression. * * @param left * @param right */
public static BinaryExpression add(Expression left, Object right) { return add(left, new LiteralExpression(right)); }
Creates an addition or concatenation expression.
Params:
  • left –
  • right –
/** * Creates an addition or concatenation expression. * * @param left * @param right */
public static BinaryExpression add(Object left, Expression right) { return add(new LiteralExpression(left), right); }
Creates an addition or concatenation expression.
Params:
  • left –
  • right –
/** * Creates an addition or concatenation expression. * * @param left * @param right */
public static BinaryExpression add(Object left, Object right) { return add(new LiteralExpression(left), new LiteralExpression(right)); }
Creates a subtraction expression.
Params:
  • left –
  • right –
/** * Creates a subtraction expression. * * @param left * @param right */
public static BinaryExpression subtract(Expression left, Expression right) { return new BinaryExpression<Number, Number>(left, right, (Number leftValue, Number rightValue) -> { Number value; if (leftValue instanceof Double || rightValue instanceof Double) { value = leftValue.doubleValue() - rightValue.doubleValue(); } else if (leftValue instanceof Float || rightValue instanceof Float) { value = leftValue.floatValue() - rightValue.floatValue(); } else if (leftValue instanceof Long || rightValue instanceof Long) { value = leftValue.longValue() - rightValue.longValue(); } else if (leftValue instanceof Integer || rightValue instanceof Integer) { value = leftValue.intValue() - rightValue.intValue(); } else if (leftValue instanceof Short || rightValue instanceof Short) { value = leftValue.shortValue() - rightValue.shortValue(); } else if (leftValue instanceof Byte || rightValue instanceof Byte) { value = leftValue.byteValue() - rightValue.byteValue(); } else { throw new UnsupportedOperationException(); } return value; }); }
Creates a subtraction expression.
Params:
  • left –
  • right –
/** * Creates a subtraction expression. * * @param left * @param right */
public static BinaryExpression subtract(Expression left, Number right) { return subtract(left, new LiteralExpression(right)); }
Creates a subtraction expression.
Params:
  • left –
  • right –
/** * Creates a subtraction expression. * * @param left * @param right */
public static BinaryExpression subtract(Number left, Expression right) { return subtract(new LiteralExpression(left), right); }
Creates a subtraction expression.
Params:
  • left –
  • right –
/** * Creates a subtraction expression. * * @param left * @param right */
public static BinaryExpression subtract(Number left, Number right) { return subtract(new LiteralExpression(left), new LiteralExpression(right)); }
Creates a multiplication expression.
Params:
  • left –
  • right –
/** * Creates a multiplication expression. * * @param left * @param right */
public static BinaryExpression multiply(Expression left, Expression right) { return new BinaryExpression<Number, Number>(left, right, (Number leftValue, Number rightValue) -> { Number value; if (leftValue instanceof Double || rightValue instanceof Double) { value = leftValue.doubleValue() * rightValue.doubleValue(); } else if (leftValue instanceof Float || rightValue instanceof Float) { value = leftValue.floatValue() * rightValue.floatValue(); } else if (leftValue instanceof Long || rightValue instanceof Long) { value = leftValue.longValue() * rightValue.longValue(); } else if (leftValue instanceof Integer || rightValue instanceof Integer) { value = leftValue.intValue() * rightValue.intValue(); } else if (leftValue instanceof Short || rightValue instanceof Short) { value = leftValue.shortValue() * rightValue.shortValue(); } else if (leftValue instanceof Byte || rightValue instanceof Byte) { value = leftValue.byteValue() * rightValue.byteValue(); } else { throw new UnsupportedOperationException(); } return value; }); }
Creates a multiplication expression.
Params:
  • left –
  • right –
/** * Creates a multiplication expression. * * @param left * @param right */
public static BinaryExpression multiply(Expression left, Number right) { return multiply(left, new LiteralExpression(right)); }
Creates a multiplication expression.
Params:
  • left –
  • right –
/** * Creates a multiplication expression. * * @param left * @param right */
public static BinaryExpression multiply(Number left, Expression right) { return multiply(new LiteralExpression(left), right); }
Creates a multiplication expression.
Params:
  • left –
  • right –
/** * Creates a multiplication expression. * * @param left * @param right */
public static BinaryExpression multiply(Number left, Number right) { return multiply(new LiteralExpression(left), new LiteralExpression(right)); }
Creates a division expression.
Params:
  • left –
  • right –
/** * Creates a division expression. * * @param left * @param right */
public static BinaryExpression divide(Expression left, Expression right) { return new BinaryExpression<Number, Number>(left, right, (Number leftValue, Number rightValue) -> { Number value; if (leftValue instanceof Double || rightValue instanceof Double) { value = leftValue.doubleValue() / rightValue.doubleValue(); } else if (leftValue instanceof Float || rightValue instanceof Float) { value = leftValue.floatValue() / rightValue.floatValue(); } else if (leftValue instanceof Long || rightValue instanceof Long) { value = leftValue.longValue() / rightValue.longValue(); } else if (leftValue instanceof Integer || rightValue instanceof Integer) { value = leftValue.intValue() / rightValue.intValue(); } else if (leftValue instanceof Short || rightValue instanceof Short) { value = leftValue.shortValue() / rightValue.shortValue(); } else if (leftValue instanceof Byte || rightValue instanceof Byte) { value = leftValue.byteValue() / rightValue.byteValue(); } else { throw new UnsupportedOperationException(); } return value; }); }
Creates a division expression.
Params:
  • left –
  • right –
/** * Creates a division expression. * * @param left * @param right */
public static BinaryExpression divide(Expression left, Number right) { return divide(left, new LiteralExpression(right)); }
Creates a division expression.
Params:
  • left –
  • right –
/** * Creates a division expression. * * @param left * @param right */
public static BinaryExpression divide(Number left, Expression<Number> right) { return divide(new LiteralExpression(left), right); }
Creates a division expression.
Params:
  • left –
  • right –
/** * Creates a division expression. * * @param left * @param right */
public static BinaryExpression divide(Number left, Number right) { return divide(new LiteralExpression(left), new LiteralExpression(right)); }
Creates a modulus expression.
Params:
  • left –
  • right –
/** * Creates a modulus expression. * * @param left * @param right */
public static BinaryExpression modulo(Expression left, Expression right) { return new BinaryExpression<Number, Number>(left, right, (Number leftValue, Number rightValue) -> { Number value; if (leftValue instanceof Double || rightValue instanceof Double) { value = leftValue.doubleValue() % rightValue.doubleValue(); } else if (leftValue instanceof Float || rightValue instanceof Float) { value = leftValue.floatValue() % rightValue.floatValue(); } else if (leftValue instanceof Long || rightValue instanceof Long) { value = leftValue.longValue() % rightValue.longValue(); } else if (leftValue instanceof Integer || rightValue instanceof Integer) { value = leftValue.intValue() % rightValue.intValue(); } else if (leftValue instanceof Short || rightValue instanceof Short) { value = leftValue.shortValue() % rightValue.shortValue(); } else if (leftValue instanceof Byte || rightValue instanceof Byte) { value = leftValue.byteValue() % rightValue.byteValue(); } else { throw new UnsupportedOperationException(); } return value; }); }
Creates a modulus expression.
Params:
  • left –
  • right –
/** * Creates a modulus expression. * * @param left * @param right */
public static BinaryExpression modulo(Expression<Number> left, Number right) { return modulo(left, new LiteralExpression(right)); }
Creates a modulus expression.
Params:
  • left –
  • right –
/** * Creates a modulus expression. * * @param left * @param right */
public static BinaryExpression modulo(Number left, Expression<Number> right) { return modulo(new LiteralExpression(left), right); }
Creates a modulus expression.
Params:
  • left –
  • right –
/** * Creates a modulus expression. * * @param left * @param right */
public static BinaryExpression modulo(Number left, Number right) { return modulo(new LiteralExpression(left), new LiteralExpression(right)); }
Creates an equality expression.
Params:
  • left –
  • right –
/** * Creates an equality expression. * * @param left * @param right */
public static BinaryExpression equalTo(Expression left, Expression right) { return new BinaryExpression<Comparable, Boolean>(left, right, (Comparable leftValue, Comparable rightValue) -> leftValue.compareTo(rightValue) == 0 ); }
Creates an equality expression.
Params:
  • left –
  • right –
/** * Creates an equality expression. * * @param left * @param right */
public static BinaryExpression equalTo(Expression left, Object right) { return equalTo(left, new LiteralExpression(right)); }
Creates an equality expression.
Params:
  • left –
  • right –
/** * Creates an equality expression. * * @param left * @param right */
public static BinaryExpression equalTo(Object left, Expression right) { return equalTo(new LiteralExpression(left), right); }
Creates an equality expression.
Params:
  • left –
  • right –
/** * Creates an equality expression. * * @param left * @param right */
public static BinaryExpression equalTo(Object left, Object right) { return equalTo(new LiteralExpression(left), new LiteralExpression(right)); }
Creates an inverse equality expression.
Params:
  • left –
  • right –
/** * Creates an inverse equality expression. * * @param left * @param right */
public static BinaryExpression notEqualTo(Expression left, Expression right) { return new BinaryExpression<Comparable, Boolean>(left, right, (leftValue, rightValue) -> leftValue.compareTo(rightValue) != 0 ); }
Creates an inverse equality expression.
Params:
  • left –
  • right –
/** * Creates an inverse equality expression. * * @param left * @param right */
public static BinaryExpression notEqualTo(Expression left, Object right) { return notEqualTo(left, new LiteralExpression(right)); }
Creates an inverse equality expression.
Params:
  • left –
  • right –
/** * Creates an inverse equality expression. * * @param left * @param right */
public static BinaryExpression notEqualTo(Object left, Expression right) { return notEqualTo(new LiteralExpression(left), right); }
Creates an inverse equality expression.
Params:
  • left –
  • right –
/** * Creates an inverse equality expression. * * @param left * @param right */
public static BinaryExpression notEqualTo(Object left, Object right) { return notEqualTo(new LiteralExpression(left), new LiteralExpression(right)); }
Creates a "greater-than" comparison expression.
Params:
  • left –
  • right –
/** * Creates a "greater-than" comparison expression. * * @param left * @param right */
public static BinaryExpression greaterThan(Expression left, Expression right) { return new BinaryExpression<Comparable, Boolean>(left, right, (leftValue, rightValue) -> leftValue.compareTo(rightValue) > 0 ); }
Creates a "greater-than" comparison expression.
Params:
  • left –
  • right –
/** * Creates a "greater-than" comparison expression. * * @param left * @param right */
public static BinaryExpression greaterThan(Expression left, Object right) { return greaterThan(left, new LiteralExpression(right)); }
Creates a "greater-than" comparison expression.
Params:
  • left –
  • right –
/** * Creates a "greater-than" comparison expression. * * @param left * @param right */
public static BinaryExpression greaterThan(Object left, Expression right) { return greaterThan(new LiteralExpression(left), right); }
Creates a "greater-than" comparison expression.
Params:
  • left –
  • right –
/** * Creates a "greater-than" comparison expression. * * @param left * @param right */
public static BinaryExpression greaterThan(Object left, Object right) { return greaterThan(new LiteralExpression(left), new LiteralExpression(right)); }
Creates a "greater-than-or-equal-to" comparison expression.
Params:
  • left –
  • right –
/** * Creates a "greater-than-or-equal-to" comparison expression. * * @param left * @param right */
public static BinaryExpression greaterThanOrEqualTo(Expression left, Expression right) { return new BinaryExpression<Comparable, Boolean>(left, right, (leftValue, rightValue) -> leftValue.compareTo(rightValue) >= 0 ); }
Creates a "greater-than-or-equal-to" comparison expression.
Params:
  • left –
  • right –
/** * Creates a "greater-than-or-equal-to" comparison expression. * * @param left * @param right */
public static BinaryExpression greaterThanOrEqualTo(Expression left, Object right) { return greaterThanOrEqualTo(left, new LiteralExpression(right)); }
Creates a "greater-than-or-equal-to" comparison expression.
Params:
  • left –
  • right –
/** * Creates a "greater-than-or-equal-to" comparison expression. * * @param left * @param right */
public static BinaryExpression greaterThanOrEqualTo(Object left, Expression right) { return greaterThanOrEqualTo(new LiteralExpression(left), right); }
Creates a "greater-than-or-equal-to" comparison expression.
Params:
  • left –
  • right –
/** * Creates a "greater-than-or-equal-to" comparison expression. * * @param left * @param right */
public static BinaryExpression greaterThanOrEqualTo(Object left, Object right) { return greaterThanOrEqualTo(new LiteralExpression(left), new LiteralExpression(right)); }
Creates a "less-than" comparison expression.
Params:
  • left –
  • right –
/** * Creates a "less-than" comparison expression. * * @param left * @param right */
public static BinaryExpression lessThan(Expression left, Expression right) { return new BinaryExpression<Comparable, Boolean>(left, right, (leftValue, rightValue) -> leftValue.compareTo(rightValue) < 0 ); }
Creates a "less-than" comparison expression.
Params:
  • left –
  • right –
/** * Creates a "less-than" comparison expression. * * @param left * @param right */
public static BinaryExpression lessThan(Expression left, Object right) { return lessThan(left, new LiteralExpression(right)); }
Creates a "less-than" comparison expression.
Params:
  • left –
  • right –
/** * Creates a "less-than" comparison expression. * * @param left * @param right */
public static BinaryExpression lessThan(Object left, Expression right) { return lessThan(new LiteralExpression(left), right); }
Creates a "less-than" comparison expression.
Params:
  • left –
  • right –
/** * Creates a "less-than" comparison expression. * * @param left * @param right */
public static BinaryExpression lessThan(Object left, Object right) { return lessThan(new LiteralExpression(left), new LiteralExpression(right)); }
Creates a "less-than-or-equal-to" comparison expression.
Params:
  • left –
  • right –
/** * Creates a "less-than-or-equal-to" comparison expression. * * @param left * @param right */
public static BinaryExpression lessThanOrEqualTo(Expression left, Expression right) { return new BinaryExpression<Comparable, Boolean>(left, right, (leftValue, rightValue) -> leftValue.compareTo(rightValue) <= 0 ); }
Creates a "less-than-or-equal-to" comparison expression.
Params:
  • left –
  • right –
/** * Creates a "less-than-or-equal-to" comparison expression. * * @param left * @param right */
public static BinaryExpression lessThanOrEqualTo(Expression left, Object right) { return lessThanOrEqualTo(left, new LiteralExpression(right)); }
Creates a "less-than-or-equal-to" comparison expression.
Params:
  • left –
  • right –
/** * Creates a "less-than-or-equal-to" comparison expression. * * @param left * @param right */
public static BinaryExpression lessThanOrEqualTo(Object left, Expression right) { return lessThanOrEqualTo(new LiteralExpression(left), right); }
Creates a "less-than-or-equal-to" comparison expression.
Params:
  • left –
  • right –
/** * Creates a "less-than-or-equal-to" comparison expression. * * @param left * @param right */
public static BinaryExpression lessThanOrEqualTo(Object left, Object right) { return lessThanOrEqualTo(new LiteralExpression(left), new LiteralExpression(right)); }
Creates a boolean "and" expression.
Params:
  • left –
  • right –
/** * Creates a boolean "and" expression. * * @param left * @param right */
public static BinaryExpression and(Expression left, Expression right) { return new BinaryExpression<Boolean, Boolean>(left, right, (leftValue, rightValue) -> leftValue && rightValue ); }
Creates a boolean "and" expression.
Params:
  • left –
  • right –
/** * Creates a boolean "and" expression. * * @param left * @param right */
public static BinaryExpression and(Expression left, Boolean right) { return and(left, new LiteralExpression(right)); }
Creates a boolean "and" expression.
Params:
  • left –
  • right –
/** * Creates a boolean "and" expression. * * @param left * @param right */
public static BinaryExpression and(Boolean left, Expression right) { return and(new LiteralExpression(left), right); }
Creates a boolean "and" expression.
Params:
  • left –
  • right –
/** * Creates a boolean "and" expression. * * @param left * @param right */
public static BinaryExpression and(Boolean left, Boolean right) { return and(new LiteralExpression(left), new LiteralExpression(right)); }
Creates a boolean "or" expression.
Params:
  • left –
  • right –
/** * Creates a boolean "or" expression. * * @param left * @param right */
public static BinaryExpression or(Expression left, Expression right) { return new BinaryExpression<Boolean, Boolean>(left, right, (leftValue, rightValue) -> leftValue || rightValue ); }
Creates a boolean "or" expression.
Params:
  • left –
  • right –
/** * Creates a boolean "or" expression. * * @param left * @param right */
public static BinaryExpression or(Expression left, Boolean right) { return or(left, new LiteralExpression(right)); }
Creates a boolean "or" expression.
Params:
  • left –
  • right –
/** * Creates a boolean "or" expression. * * @param left * @param right */
public static BinaryExpression or(Boolean left, Expression right) { return or(new LiteralExpression(left), right); }
Creates a boolean "or" expression.
Params:
  • left –
  • right –
/** * Creates a boolean "or" expression. * * @param left * @param right */
public static BinaryExpression or(Boolean left, Boolean right) { return or(new LiteralExpression(left), new LiteralExpression(right)); }
Creates a numeric negation expression.
Params:
  • operand –
/** * Creates a numeric negation expression. * * @param operand */
public static UnaryExpression negate(Expression operand) { return new UnaryExpression<Number, Number>(operand, (value) -> { Class<? extends Number> type = value.getClass(); if (type == Byte.class) { return -value.byteValue(); } else if (type == Short.class) { return -value.shortValue(); } else if (type == Integer.class) { return -value.intValue(); } else if (type == Long.class) { return -value.longValue(); } else if (type == Float.class) { return -value.floatValue(); } else if (type == Double.class) { return -value.doubleValue(); } else { throw new UnsupportedOperationException(); } }); }
Creates a numeric negation expression.
Params:
  • operand –
/** * Creates a numeric negation expression. * * @param operand */
public static UnaryExpression negate(Number operand) { return negate(new LiteralExpression(operand)); }
Creates a boolean "not" expression.
Params:
  • operand –
/** * Creates a boolean "not" expression. * * @param operand */
public static UnaryExpression not(Expression operand) { return new UnaryExpression<Boolean, Boolean>(operand, (value) -> !value); }
Creates a boolean "not" expression.
Params:
  • operand –
/** * Creates a boolean "not" expression. * * @param operand */
public static UnaryExpression not(Boolean operand) { return not(new LiteralExpression(operand)); }
Parses a string representation of an expression into an expression tree.
Params:
  • value – The string representation of the expression.
/** * Parses a string representation of an expression into an expression * tree. * * @param value * The string representation of the expression. */
public static Expression valueOf(String value) { if (value == null) { throw new NullPointerException(); } Parser parser = new Parser(); Expression expression; try { expression = parser.parse(new StringReader(value)); } catch (IOException exception) { throw new RuntimeException(exception); } return expression; } }