[CCSDK-6] Populate seed code
[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 }