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

com.consol.citrus.util.BooleanExpressionParser Maven / Gradle / Ivy

/*
 * Copyright 2006-2010 the original author or authors.
 *
 * Licensed 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 com.consol.citrus.util;

import java.util.*;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import com.consol.citrus.exceptions.CitrusRuntimeException;

/**
 * Parses boolean expression strings and evaluates to boolean result.
 * 
 * @author Christoph Deppisch
 */
@SuppressWarnings("unchecked")
public final class BooleanExpressionParser {
    
    /** List of known operators */
    private static final List OPERATORS = new ArrayList(
            CollectionUtils.arrayToList(new String[]{"(", "=", "and", "or", "lt", "lt=", "gt", "gt=", ")"}));

    /** List of known boolean values */
    private static final List BOOLEAN_VALUES = new ArrayList(
            CollectionUtils.arrayToList(new String[]{"true", "false"}));
    
    /**
     * Logger
     */
    private static Logger log = LoggerFactory.getLogger(BooleanExpressionParser.class);

    /**
     * Prevent instantiation.
     */
    private BooleanExpressionParser() {
    }
    
    /**
     * Perform evaluation of boolean expression string.
     * @param expression
     * @throws CitrusRuntimeException
     * @return
     */
    public static boolean evaluate(String expression) {
        Stack operators = new Stack();
        Stack values = new Stack();
        boolean result = true;

        char actChar;

        try {
            for (int i = 0; i < expression.length(); i++) {
                actChar = expression.charAt(i);
    
                if (actChar == '('){
                    operators.push("(");
                } else if (actChar == ' ') {
                    continue; //ignore
                } else if (actChar == ')') {
                    String operator = operators.pop();
                    while (!(operator).equals("(")) {
                        values.push(getBooleanResultAsString(operator, values.pop(), values.pop()));
                        operator = operators.pop();
                    }
                } else if (!Character.isDigit(actChar)) {
                    StringBuffer operatorBuffer = new StringBuffer();
    
                    int m = i;
                    do {
                        operatorBuffer.append(actChar);
                        m++;
                        
                        if (m < expression.length()) {
                            actChar = expression.charAt(m);
                        }
                    } while (m < expression.length() && !Character.isDigit(actChar) && !(actChar == ' ') && !(actChar == '('));
    
                    i = m - 1;

                    if (BOOLEAN_VALUES.contains(operatorBuffer.toString())) {
                        values.push(Boolean.valueOf(operatorBuffer.toString()) ? "1" : "0");
                    } else {
                        operators.push(validateOperator(operatorBuffer.toString()));
                    }
                } else if (Character.isDigit(actChar)) {
                    StringBuffer digitBuffer = new StringBuffer();
    
                    int m = i;
                    do {
                        digitBuffer.append(actChar);
                        m++;
                        
                        if (m < expression.length()) {
                            actChar = expression.charAt(m);
                        }
                    } while (m < expression.length() && Character.isDigit(actChar));
    
                    i = m - 1;
    
                    values.push(digitBuffer.toString());
                }
            }
    
            while (!operators.isEmpty()) {
                values.push(getBooleanResultAsString(operators.pop(), values.pop(), values.pop()));
            }
    
            String value = values.pop();

            if (value.equals("0")) {
                value = "false";
            } else if (value.equals("1")) {
                value = "true";
            }

            result = Boolean.valueOf(value).booleanValue();
    
            if (log.isDebugEnabled()) {
                log.debug("Boolean expression " + expression + " evaluates to " + result);
            }
        } catch(EmptyStackException e) {
            throw new CitrusRuntimeException("Unable to parse boolean expression '" + expression + "'. Maybe expression is incomplete!", e);
        }

        return result;
    }
    
    /**
     * Check if operator is known to this class.
     * @param operator to validate
     * @return the operator itself.
     * @throws CitrusRuntimeException
     */
    private static String validateOperator(String operator) {
        if (!OPERATORS.contains(operator)) {
            throw new CitrusRuntimeException("Unknown operator '" + operator + "'");
        }
        return operator;
    }

    /**
     * Evaluates a boolean expression to a String representation (true/false).
     * @param operator
     * @param value1
     * @param value2
     * @return true/false as String
     */
    private static String getBooleanResultAsString(String operator, String value1, String value2) {
        if (operator.equals("lt")) {
            return Boolean.valueOf(Integer.valueOf(value2).intValue() < Integer.valueOf(value1).intValue()).toString();
        } else if (operator.equals("lt=")) {
            return Boolean.valueOf(Integer.valueOf(value2).intValue() <= Integer.valueOf(value1).intValue()).toString();
        } else if (operator.equals("gt")) {
            return Boolean.valueOf(Integer.valueOf(value2).intValue() > Integer.valueOf(value1).intValue()).toString();
        } else if (operator.equals("gt=")) {
            return Boolean.valueOf(Integer.valueOf(value2).intValue() >= Integer.valueOf(value1).intValue()).toString();
        } else if (operator.equals("=")) {
            return Boolean.valueOf(Integer.valueOf(value2).intValue() == Integer.valueOf(value1).intValue()).toString();
        } else if (operator.equals("and")) {
            return Boolean.valueOf(Boolean.valueOf(value2).booleanValue() && Boolean.valueOf(value1).booleanValue()).toString();
        } else if (operator.equals("or")) {
            return Boolean.valueOf(Boolean.valueOf(value2).booleanValue() || Boolean.valueOf(value1).booleanValue()).toString();
        } else {
            throw new CitrusRuntimeException("Unknown operator '" + operator + "'");
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy