All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ow2.bonita.expression.BooleanExpression Maven / Gradle / Ivy

/**
 * Copyright (C) 2006  Bull S. A. S.
 * Bull, Rue Jean Jaures, B.P.68, 78340, Les Clayes-sous-Bois
 * This library is free software; you can redistribute it and/or modify it under the terms
 * of the GNU Lesser General Public License as published by the Free Software Foundation
 * version 2.1 of the License.
 * This library 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 Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public License along with this
 * program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
 * Floor, Boston, MA  02110-1301, USA.
 **/
package org.ow2.bonita.expression;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import org.ow2.bonita.util.Misc;

/**
 * 
 * @author chaffotm
 *
 */
public class BooleanExpression {

  private static final String JAVA_FIELD_PATTERN = "^[a-z][a-zA-Z0-9]*$";
  private List tokens;

  /**
   * 
   * @param expression the expression
   * @throws InvalidExpressionException if the expression is not valid
   */
  public BooleanExpression(final String expression)
  throws InvalidExpressionException {
    Misc.checkArgsNotNull(expression);
    tokens = new Vector();
    checkExpression(formatExpression(expression));
  }

  /**
   * Checks whether the expression given in parameter is a boolean expression.
   * @param expression the expression to check
   * @throws InvalidExpressionException if the expression is not valid
   */
  private void checkExpression(String expression)
  throws InvalidExpressionException {
    expression = expression.trim();
    if (expression.length() == 0) {
      throw new InvalidExpressionException(expression,
          "The expression cannot be an empty String");
    }
    if (expression.startsWith(KeyWord.LEFT_PARENTHESIS.value())
        && isABloc(expression)) {
      tokens.add(KeyWord.LEFT_PARENTHESIS.value());
      checkExpression(expression.substring(1, expression.length() - 1));
      tokens.add(KeyWord.RIGHT_PARENTHESIS.value());
    } else {
      if (isField(expression)) {
        if (!isConformField(expression)) {
          throw new InvalidExpressionException(expression,
               "The field is not conform to expression " + JAVA_FIELD_PATTERN);
        } else {
          tokens.add(expression);
        }
      } else {
        String not = Character.toString(expression.charAt(0));
        if (KeyWord.NOT.value().equals(not)) {
          tokens.add(KeyWord.NOT.value());
          checkExpression(expression.substring(1));
        } else {
          List expressions =
            getExpressionsFromBinaryOperation(expression);
          String operator = expressions.get(0);
          String left = expressions.get(1).trim();
          String right = expressions.get(2).trim();
          if (left.length() == 0) {
            throw new InvalidExpressionException(expression,
                "The left expression is missing");
          }
          if (operator.length() == 0) {
            throw new InvalidExpressionException(expression,
                "An operator is missing");
          }
          if (right.length() == 0) {
            throw new InvalidExpressionException(expression,
                "The right expression is missing");
          }
          if (operator.equals(KeyWord.AND.value())
              || operator.equals(KeyWord.OR.value())
              || operator.equals(KeyWord.XOR.value())) {
            
            checkExpression(left);
            tokens.add(operator);
            checkExpression(right);
          } else {
            throw new InvalidExpressionException(expression,
                "Unknown operator : \"" + operator + "\"");
          }
        }
      }
    }
  }

  /**
   * Checks whether the expression is a bloc.
   * A bloc is a well-formed expression in parenthesis .
   * (the number of left parentheses equals the number of right parentheses)
   * @param expression the expression to check
   * @return true if it is a bloc; false otherwise
   * @throws InvalidExpressionException if the expression is invalid
   */
  private static boolean isABloc(final String expression)
  throws InvalidExpressionException {
    boolean bloc = false;
    if(expression.startsWith(KeyWord.LEFT_PARENTHESIS.value())) {
      int index = 1;
      int count = 1;
      char current;
      while (index < expression.length() && count > 0) {
        current = expression.charAt(index);
        if (KeyWord.LEFT_PARENTHESIS.value().equals(String.valueOf(current))) {
          count++;
        } else if (
            KeyWord.RIGHT_PARENTHESIS.value().equals(String.valueOf(current))) {
          count--;
        }
        index++;
      }
      if (count > 0) {
        throw new InvalidExpressionException(expression,
            "A right parenthesis is missing");
      }
      if (index == expression.length()) {
        bloc = true;
      }
    }
    return bloc;
  }

  /**
   * Returns the operator and both expressions from a binary operation.
   * @param expression the expression to split
   * @return the list containing the operator, the left expression and
   * the right expression. (in this order)
   * @throws InvalidExpressionException if the expression is invalid
   */
  private static List getExpressionsFromBinaryOperation(
      final String expression) throws InvalidExpressionException {
    List exp = new ArrayList();
    int count = 0;
    int i = 1;
    int length = expression.length();
    if (expression.startsWith(KeyWord.LEFT_PARENTHESIS.value())) {
      count = 1;
      char current;
      while (i < length && count > 0) {
        current = expression.charAt(i);
        if (KeyWord.LEFT_PARENTHESIS.value().equals(String.valueOf(current))) {
          count++;
        } else if (
            KeyWord.RIGHT_PARENTHESIS.value().equals(String.valueOf(current))) {
          count--;
        }
        i++;
      }
      if (count > 0) {
        throw new InvalidExpressionException(expression,
            "A right parenthesis is missing");
      }
    } else {
      i = 0;
      char current;
      String oper = "";
      boolean op = false;
      while (i < (length - 1) && !op) {
        current = expression.charAt(i);
        oper = String.valueOf(current);
        if (oper.equals(KeyWord.AND.value()) || oper.equals(KeyWord.OR.value())
            || oper.equals(KeyWord.XOR.value())) {
          op = true;
        }
        i++;
      }
      if (!op) {
        throw new InvalidExpressionException(expression,
            "Operator not valid");
      }
      i--;
    }
    String left = expression.substring(0, i);
    String tail = expression.substring(i);
    String operator = getOperator(tail);
    int cut = tail.indexOf(operator);
    String right = tail.substring(cut + operator.length(), tail.length());
    exp.add(operator);
    exp.add(left);
    exp.add(right);
    return exp;
  }

  /**
   * Gets the first operator from the given expression.
   * It can be a valid or an invalid operator.
   * @param expression the expression
   * @return the first operator
   */
  private static String getOperator(String expression) {
    expression = expression.trim();
    String operator = expression.substring(0, 1);
    if (expression.startsWith(KeyWord.LEFT_PARENTHESIS.value())
        || expression.startsWith(KeyWord.NOT.value())) {
      operator = "";
    } else if (!operator.equals(KeyWord.AND.value())
        && !operator.equals(KeyWord.OR.value())
        && !operator.equals(KeyWord.XOR.value())) {
      int index = 0;
      boolean end = false;
      char c = 'a';
      operator = "";
      while (index < expression.length() && !end) {
        c = expression.charAt(index);
        operator += c;
        if (Character.isWhitespace(c)) {
          end = true;
        }
        index++;
      }
    }
    return operator;
  }

  /**
   * Checks whether the expression is a field.
   * A field contains only a chain of letters and digits.
   * @param expression the expression
   * @return true if the expression is a field; false otherwise
   */
  private static boolean isField(final String expression) {
    int i = 0;
    char ch = ' ';
    boolean field = true;
    while (i < expression.length() && field) {
      ch = expression.charAt(i);
      if (!Character.isJavaIdentifierPart(ch)) {
        field = false;
      }
      i++;
    }
    return field;
  }

  /**
   * Checks if the field is conform to the java field pattern:
   * "^[a-z][a-zA-Z0-9]*$".
   * @param expression the expression
   * @return true if this expression matches this pattern; false otherwise
   */
  private static boolean isConformField(final String expression) {
    return expression.matches(JAVA_FIELD_PATTERN);
  }

  /**
   * Gets an formatted expression. Tab, newline and carriage-return characters
   * are replaced by a space character.
   * @param expression
   * @return
   */
  private static String formatExpression(String expression) {
    expression = expression.replaceAll("\t", " ");
    expression = expression.replaceAll("\n", " ");
    return expression.replaceAll("\r", " ");
  }

  public List getTokens() {
    return tokens;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy