2  * ============LICENSE_START=======================================================
 
   4  * ================================================================================
 
   5  * Copyright (C) 2017 AT&T Intellectual Property. All rights
 
   7  * ================================================================================
 
   8  * Licensed under the Apache License, Version 2.0 (the "License");
 
   9  * you may not use this file except in compliance with the License.
 
  10  * You may obtain a copy of the License at
 
  12  *      http://www.apache.org/licenses/LICENSE-2.0
 
  14  * Unless required by applicable law or agreed to in writing, software
 
  15  * distributed under the License is distributed on an "AS IS" BASIS,
 
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  17  * See the License for the specific language governing permissions and
 
  18  * limitations under the License.
 
  19  * ============LICENSE_END=========================================================
 
  22 package org.onap.ccsdk.sli.adaptors.util.expr;
 
  26 public class ExpressionEvaluator {
 
  28     public static long evalLong(String expr, Map<String, String> vars) {
 
  29         return (long) evalFloat(expr, vars);
 
  32     public static float evalFloat(String expr, Map<String, String> vars) {
 
  34         int sl = expr.length();
 
  36             throw new IllegalArgumentException("Cannot interpret empty string.");
 
  39         // Remove parentheses if any
 
  40         if (expr.charAt(0) == '(' && expr.charAt(sl - 1) == ')') {
 
  41             return evalFloat(expr.substring(1, sl - 1), vars);
 
  44         // Look for operators in the order of least priority
 
  45         String[] sss = findOperator(expr, "-", true);
 
  47             return evalFloat(sss[0], vars) - evalFloat(sss[1], vars);
 
  50         sss = findOperator(expr, "+", true);
 
  52             return evalFloat(sss[0], vars) + evalFloat(sss[1], vars);
 
  55         sss = findOperator(expr, "/", true);
 
  57             return evalFloat(sss[0], vars) / evalFloat(sss[1], vars);
 
  60         sss = findOperator(expr, "*", true);
 
  62             return evalFloat(sss[0], vars) * evalFloat(sss[1], vars);
 
  65         // Check if expr is a number
 
  67             return Float.valueOf(expr);
 
  68         } catch (Exception e) {
 
  72         String v = vars.get(expr);
 
  74             return Float.valueOf(v);
 
  75         } catch (Exception e) {
 
  80     public static String evalString(String expr, Map<String, String> vars) {
 
  82         int sl = expr.length();
 
  84             throw new IllegalArgumentException("Cannot interpret empty string.");
 
  87         // Remove parentheses if any
 
  88         if (expr.charAt(0) == '(' && expr.charAt(sl - 1) == ')') {
 
  89             return evalString(expr.substring(1, sl - 1), vars);
 
  92         // Look for operators in the order of least priority
 
  93         String[] sss = findOperator(expr, "+", true);
 
  95             return evalString(sss[0], vars) + evalString(sss[1], vars);
 
  98         // Check if expr is a number
 
 100             return Float.valueOf(expr).toString();
 
 101         } catch (Exception e) {
 
 105         if (expr.charAt(0) == '"' && expr.charAt(sl - 1) == '"') {
 
 106             return expr.substring(1, sl - 1);
 
 108         if (expr.charAt(0) == '\'' && expr.charAt(sl - 1) == '\'') {
 
 109             return expr.substring(1, sl - 1);
 
 112         // Must be a variable
 
 113         String v = vars.get(expr);
 
 114         return v != null ? v : "";
 
 117     public static boolean evalBoolean(String expr, Map<String, String> vars) {
 
 119         int sl = expr.length();
 
 121             throw new IllegalArgumentException("Cannot interpret empty string.");
 
 124         if (expr.equalsIgnoreCase("true")) {
 
 128         if (expr.equalsIgnoreCase("false")) {
 
 132         // Remove parentheses if any
 
 133         if (expr.charAt(0) == '(' && expr.charAt(sl - 1) == ')') {
 
 134             return evalBoolean(expr.substring(1, sl - 1), vars);
 
 137         // Look for operators in the order of least priority
 
 138         String[] sss = findOperator(expr, "or", true);
 
 140             return evalBoolean(sss[0], vars) || evalBoolean(sss[1], vars);
 
 143         sss = findOperator(expr, "and", true);
 
 145             return evalBoolean(sss[0], vars) && evalBoolean(sss[1], vars);
 
 148         sss = findOperator(expr, "not", true);
 
 150             return !evalBoolean(sss[1], vars);
 
 153         sss = findOperator(expr, "!=", false);
 
 155             sss = findOperator(expr, "<>", false);
 
 158             return !evalString(sss[0], vars).equals(evalString(sss[1], vars));
 
 161         sss = findOperator(expr, "==", false);
 
 163             sss = findOperator(expr, "=", false);
 
 166             return evalString(sss[0], vars).equals(evalString(sss[1], vars));
 
 169         sss = findOperator(expr, ">=", false);
 
 171             return evalLong(sss[0], vars) >= evalLong(sss[1], vars);
 
 174         sss = findOperator(expr, ">", false);
 
 176             return evalLong(sss[0], vars) > evalLong(sss[1], vars);
 
 179         sss = findOperator(expr, "<=", false);
 
 181             return evalLong(sss[0], vars) <= evalLong(sss[1], vars);
 
 184         sss = findOperator(expr, "<", false);
 
 186             return evalLong(sss[0], vars) < evalLong(sss[1], vars);
 
 189         throw new IllegalArgumentException("Cannot interpret '" + expr + "': Invalid expression.");
 
 192     private static String[] findOperator(String s, String op, boolean delimiterRequired) {
 
 193         int opl = op.length();
 
 195         String delimiters = " \0\t\r\n()";
 
 196         int pcount = 0, qcount = 0;
 
 197         for (int i = 0; i < sl; i++) {
 
 198             char c = s.charAt(i);
 
 199             if (c == '(' && qcount == 0) {
 
 201             } else if (c == ')' && qcount == 0) {
 
 204                     throw new IllegalArgumentException("Cannot interpret '" + s + "': Parentheses do not match.");
 
 206             } else if (c == '\'') {
 
 207                 qcount = (qcount + 1) % 2;
 
 208             } else if (i <= sl - opl && pcount == 0 && qcount == 0) {
 
 209                 String ss = s.substring(i, i + opl);
 
 210                 if (ss.equalsIgnoreCase(op)) {
 
 211                     boolean found = true;
 
 212                     if (delimiterRequired) {
 
 213                         // Check for delimiter before and after to make sure it is not part of another word
 
 214                         char chbefore = '\0';
 
 216                             chbefore = s.charAt(i - 1);
 
 220                             chafter = s.charAt(i + opl);
 
 222                         found = delimiters.indexOf(chbefore) >= 0 && delimiters.indexOf(chafter) >= 0;
 
 225                         // We've found the operator, split the string
 
 226                         String[] sss = new String[2];
 
 227                         sss[0] = s.substring(0, i);
 
 228                         sss[1] = s.substring(i + opl);
 
 235             throw new IllegalArgumentException("Cannot interpret '" + s + "': Parentheses do not match.");
 
 238             throw new IllegalArgumentException("Cannot interpret '" + s + "': No closing '.");
 
 243     @SuppressWarnings("unused")
 
 244     private static Object parseObject(String s) {
 
 248             throw new IllegalArgumentException("Cannot interpret empty string.");
 
 250         if (s.equalsIgnoreCase("null")) {
 
 253         if (s.charAt(0) == '\'') {
 
 254             if (sl < 2 || s.charAt(sl - 1) != '\'') {
 
 255                 throw new IllegalArgumentException("Cannot interpret '" + s + "': No closing '.");
 
 257             return s.substring(1, sl - 1);
 
 259         // Not in quotes - must be a number
 
 261             return Long.valueOf(s);
 
 262         } catch (Exception e) {
 
 265             return Double.valueOf(s);
 
 266         } catch (Exception e) {
 
 267             throw new IllegalArgumentException("Cannot interpret '" + s + "': Invalid number.");