345a6263c8ee8abb4d6ae800ffb80d1f9c212d6f
[ccsdk/sli/adaptors.git] / resource-assignment / provider / src / main / java / org / openecomp / sdnc / util / expr / ExpressionEvaluator.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * openECOMP : SDN-C
4  * ================================================================================
5  * Copyright (C) 2017 ONAP Intellectual Property. All rights
6  * reserved.
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
11  * 
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  * 
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=========================================================
20  */
21
22 package org.openecomp.sdnc.util.expr;
23
24 import java.util.Map;
25
26 public class ExpressionEvaluator {
27
28     public static long evalLong(String expr, Map<String, Object> vars) {
29         return (long) evalFloat(expr, vars);
30     }
31
32     public static float evalFloat(String expr, Map<String, Object> vars) {
33         expr = expr.trim();
34         int sl = expr.length();
35         if (sl == 0)
36             throw new IllegalArgumentException("Cannot interpret empty string.");
37
38         // Remove parentheses if any
39         if (expr.charAt(0) == '(' && expr.charAt(sl - 1) == ')')
40             return evalFloat(expr.substring(1, sl - 1), vars);
41
42         // Look for operators in the order of least priority
43         String[] sss = findOperator(expr, "-", true);
44         if (sss != null)
45             return evalFloat(sss[0], vars) - evalFloat(sss[1], vars);
46
47         sss = findOperator(expr, "+", true);
48         if (sss != null)
49             return evalFloat(sss[0], vars) + evalFloat(sss[1], vars);
50
51         sss = findOperator(expr, "/", true);
52         if (sss != null)
53             return evalFloat(sss[0], vars) / evalFloat(sss[1], vars);
54
55         sss = findOperator(expr, "*", true);
56         if (sss != null)
57             return evalFloat(sss[0], vars) * evalFloat(sss[1], vars);
58
59         // Check if expr is a number
60         try {
61             return Float.valueOf(expr);
62         } catch (Exception e) {
63         }
64
65         // Must be a variable
66         Object v = vars.get(expr);
67         if (v != null) {
68             if (v instanceof Float)
69                 return (Float) v;
70             if (v instanceof Long)
71                 return (Long) v;
72             if (v instanceof Integer)
73                 return (Integer) v;
74         }
75         return 0;
76     }
77
78     public static boolean evalBoolean(String expr, Map<String, Object> vars) {
79         expr = expr.trim();
80         int sl = expr.length();
81         if (sl == 0)
82             throw new IllegalArgumentException("Cannot interpret empty string.");
83
84         if (expr.equalsIgnoreCase("true"))
85             return true;
86
87         if (expr.equalsIgnoreCase("false"))
88             return false;
89
90         // Remove parentheses if any
91         if (expr.charAt(0) == '(' && expr.charAt(sl - 1) == ')')
92             return evalBoolean(expr.substring(1, sl - 1), vars);
93
94         // Look for operators in the order of least priority
95         String[] sss = findOperator(expr, "or", true);
96         if (sss != null)
97             return evalBoolean(sss[0], vars) || evalBoolean(sss[1], vars);
98
99         sss = findOperator(expr, "and", true);
100         if (sss != null)
101             return evalBoolean(sss[0], vars) && evalBoolean(sss[1], vars);
102
103         sss = findOperator(expr, "not", true);
104         if (sss != null)
105             return !evalBoolean(sss[1], vars);
106
107         sss = findOperator(expr, "!=", false);
108         if (sss == null)
109             sss = findOperator(expr, "<>", false);
110         if (sss != null)
111             return evalLong(sss[0], vars) != evalLong(sss[1], vars);
112
113         sss = findOperator(expr, "==", false);
114         if (sss == null)
115             sss = findOperator(expr, "=", false);
116         if (sss != null)
117             return evalLong(sss[0], vars) == evalLong(sss[1], vars);
118
119         sss = findOperator(expr, ">=", false);
120         if (sss != null)
121             return evalLong(sss[0], vars) >= evalLong(sss[1], vars);
122
123         sss = findOperator(expr, ">", false);
124         if (sss != null)
125             return evalLong(sss[0], vars) > evalLong(sss[1], vars);
126
127         sss = findOperator(expr, "<=", false);
128         if (sss != null)
129             return evalLong(sss[0], vars) <= evalLong(sss[1], vars);
130
131         sss = findOperator(expr, "<", false);
132         if (sss != null)
133             return evalLong(sss[0], vars) < evalLong(sss[1], vars);
134
135         throw new IllegalArgumentException("Cannot interpret '" + expr + "': Invalid expression.");
136     }
137
138     private static String[] findOperator(String s, String op, boolean delimiterRequired) {
139         int opl = op.length();
140         int sl = s.length();
141         String delimiters = " \0\t\r\n()";
142         int pcount = 0, qcount = 0;
143         for (int i = 0; i < sl; i++) {
144             char c = s.charAt(i);
145             if (c == '(' && qcount == 0)
146                 pcount++;
147             else if (c == ')' && qcount == 0) {
148                 pcount--;
149                 if (pcount < 0)
150                     throw new IllegalArgumentException("Cannot interpret '" + s + "': Parentheses do not match.");
151             } else if (c == '\'')
152                 qcount = (qcount + 1) % 2;
153             else if (i <= sl - opl && pcount == 0 && qcount == 0) {
154                 String ss = s.substring(i, i + opl);
155                 if (ss.equalsIgnoreCase(op)) {
156                     boolean found = true;
157                     if (delimiterRequired) {
158                         // Check for delimiter before and after to make sure it is not part of another word
159                         char chbefore = '\0';
160                         if (i > 0)
161                             chbefore = s.charAt(i - 1);
162                         char chafter = '\0';
163                         if (i < sl - opl)
164                             chafter = s.charAt(i + opl);
165                         found = delimiters.indexOf(chbefore) >= 0 && delimiters.indexOf(chafter) >= 0;
166                     }
167                     if (found) {
168                         // We've found the operator, split the string
169                         String[] sss = new String[2];
170                         sss[0] = s.substring(0, i);
171                         sss[1] = s.substring(i + opl);
172                         return sss;
173                     }
174                 }
175             }
176         }
177         if (pcount > 0)
178             throw new IllegalArgumentException("Cannot interpret '" + s + "': Parentheses do not match.");
179         if (qcount > 0)
180             throw new IllegalArgumentException("Cannot interpret '" + s + "': No closing '.");
181         return null;
182     }
183
184     private static Object parseObject(String s) {
185         s = s.trim();
186         int sl = s.length();
187         if (sl == 0)
188             throw new IllegalArgumentException("Cannot interpret empty string.");
189         if (s.equalsIgnoreCase("null"))
190             return null;
191         if (s.charAt(0) == '\'') {
192             if (sl < 2 || s.charAt(sl - 1) != '\'')
193                 throw new IllegalArgumentException("Cannot interpret '" + s + "': No closing '.");
194             return s.substring(1, sl - 1);
195         }
196         // Not in quotes - must be a number
197         try {
198             return Long.valueOf(s);
199         } catch (Exception e) {
200         }
201         try {
202             return Double.valueOf(s);
203         } catch (Exception e) {
204             throw new IllegalArgumentException("Cannot interpret '" + s + "': Invalid number.");
205         }
206     }
207 }