ed75254bb28e377c07c88c63f4c81a8aaa9c8634
[controller.git] / opendaylight / md-sal / sal-dom-xsql / src / main / java / org / opendaylight / controller / md / sal / dom / xsql / XSQLCriteria.java
1 package org.opendaylight.controller.md.sal.dom.xsql;
2
3 import java.io.Serializable;
4 import java.lang.reflect.Method;
5 import java.util.Map;
6 import java.util.concurrent.ConcurrentHashMap;
7
8 public class XSQLCriteria implements Serializable {
9     private static final long serialVersionUID = 1L;
10
11     private static final String operators[] =
12         new String[] {" and ", " or ", ">=", "<=", "!=", "=", ">", "<", "like",
13             "is null", "not null", "skip"};
14     private static final String STRING_CHAR = "'";
15
16     public static final int OP_CODE_AND = 0;
17     public static final int OP_CODE_OR = 1;
18     public static final int OP_CODE_GTEQ = 2;
19     public static final int OP_CODE_LTEQ = 3;
20     public static final int OP_CODE_NOT_EQ = 4;
21     public static final int OP_CODE_EQUAL = 5;
22     public static final int OP_CODE_GT = 6;
23     public static final int OP_CODE_LT = 7;
24     public static final int OP_CODE_LIKE = 8;
25     public static final int OP_CODE_NULL = 9;
26     public static final int OP_CODE_NOT_NULL = 10;
27     public static final int OP_CODE_SKIP = 11;
28
29     private XSQLCriteria left = null;
30     private XSQLCriteria right = null;
31
32     private int operation = -1;
33
34     private Object leftValue = null;
35     private Object rightValue = null;
36     private String criteria = null;
37
38     private static final Map<Class<?>, Map<String, Method>> methodCache =
39         new ConcurrentHashMap<Class<?>, Map<String, Method>>();
40
41     public XSQLCriteria(final String data, final int parentOperation) {
42         criteria = data;
43         parse(data, parentOperation);
44     }
45
46     private void parse(String data, int parentOperation) {
47
48         data = data.trim();
49
50         int index1 = data.indexOf("(");
51         if (index1 != -1) {
52             String leftCondition = data.substring(0, index1).trim();
53             if (leftCondition.trim().equals("")) {
54                 int index2 = data.lastIndexOf(")");
55                 if (index2 < data.length() - 1) {
56                     String rtValue = data.substring(index2 + 1).trim();
57                     if (!rtValue.equals("")) {
58                         left =
59                             new XSQLCriteria(data.substring(index1 + 1, index2),
60                                 parentOperation);
61                         data = data.substring(index2 + 1);
62                     } else {
63                         data = data.substring(1, index2);
64                     }
65                 } else {
66                     data = data.substring(1, index2);
67                 }
68             } else {
69                 right = new XSQLCriteria(
70                     data.substring(index1 + 1, data.length() - 1),
71                     parentOperation);
72                 data = data.substring(0, index1);
73             }
74         }
75
76         for (int i = 0; i < operators.length; i++) {
77             index1 = data.indexOf(operators[i]);
78             if (index1 != -1) {
79                 this.operation = i;
80                 if (left == null) {
81                     left = new XSQLCriteria(data.substring(0, index1),
82                         this.operation);
83                 }
84                 if (left.leftValue != null && left.rightValue == null
85                     && left.right == null) {
86                     leftValue = left.leftValue;
87                     left = null;
88                 }
89                 if (right == null) {
90                     right = new XSQLCriteria(
91                         data.substring(index1 + operators[i].length()),
92                         this.operation);
93                 }
94                 if (right.leftValue != null && right.rightValue == null
95                     && right.right == null) {
96                     rightValue = right.leftValue;
97                     right = null;
98                 }
99                 return;
100             }
101         }
102
103         if (data.startsWith("'") && data.endsWith("'")) {
104             data = data.substring(1, data.length() - 1);
105         }
106
107         if (parentOperation == OP_CODE_LIKE && data.startsWith("%") && data.endsWith("%")
108             && data.substring(1, data.length() - 1).indexOf("%") == -1) {
109             data = data.substring(1, data.length() - 1);
110         }
111
112         leftValue = data;
113     }
114
115     public static Object getValue(Object element, String propertyName) {
116         try {
117             Map<String, Method> cache = methodCache.get(element.getClass());
118             if (cache == null) {
119                 cache = new ConcurrentHashMap<String, Method>();
120                 methodCache.put(element.getClass(), cache);
121             }
122
123             Method m = cache.get(propertyName);
124             if (m == null) {
125                 Method methods[] = element.getClass().getMethods();
126                 for (Method mm : methods) {
127                     if (mm.getName().equals(propertyName) || mm.getName()
128                         .equals("get" + propertyName) || mm.getName()
129                         .equals("is" + propertyName)) {
130                         m = mm;
131                         m.setAccessible(true);
132                         cache.put(propertyName, m);
133                         break;
134                     }
135                 }
136             }
137
138             Object value = null;
139             if (m == null) {
140                 return null;
141             }
142             if (m.getParameterTypes() == null
143                 || m.getParameterTypes().length == 0) {
144                 value = m.invoke(element, null);
145             } else {
146                 if (String.class.isAssignableFrom(m.getParameterTypes()[0])) {
147                     return null;
148                 }
149                 Object arg = m.getParameterTypes()[0].newInstance();
150                 value = m.invoke(element, arg);
151             }
152             return value;
153         } catch (Exception err) {
154             err.printStackTrace();
155         }
156         return null;
157     }
158
159     public int isObjectFitCriteria(Object element, String propertyName) {
160         Object value = getValue(element, propertyName);
161         if (value != null) {
162             value = value.toString();
163         }
164         return checkValue(value);
165     }
166
167     public int checkValue(Object value) {
168         if (leftValue != null && rightValue != null) {
169             Object aSide = null;
170             Object bSide = null;
171             if (leftValue.equals("?")) {
172                 aSide = value;
173             } else {
174                 aSide = leftValue;
175             }
176
177             if (rightValue.equals("?")) {
178                 bSide = value;
179             } else {
180                 bSide = rightValue;
181             }
182             if (operation != OP_CODE_SKIP && operation != OP_CODE_NULL) {
183                 if (aSide == null && bSide != null) {
184                     return 0;
185                 } else if (aSide != null && bSide == null) {
186                     return 0;
187                 } else if (aSide == null && bSide == null) {
188                     return 1;
189                 }
190             }
191             switch (operation) {
192                 case OP_CODE_EQUAL:
193                     if (aSide.equals(bSide)) {
194                         return 1;
195                     } else {
196                         return 0;
197                     }
198                 case OP_CODE_NOT_EQ:
199                     if (!aSide.equals(bSide)) {
200                         return 1;
201                     } else {
202                         return 0;
203                     }
204                 case OP_CODE_LIKE:
205                     if (aSide.toString().indexOf(bSide.toString()) != -1) {
206                         return 1;
207                     } else {
208                         return 0;
209                     }
210                 case OP_CODE_NULL:
211                     if (aSide == null) {
212                         return 1;
213                     } else {
214                         return 0;
215                     }
216                 case OP_CODE_NOT_NULL:
217                     if (aSide != null) {
218                         return 1;
219                     } else {
220                         return 0;
221                     }
222                 case OP_CODE_GT:
223                     if (aSide == null || bSide == null) {
224                         return 0;
225                     }
226                     if (Double.parseDouble(aSide.toString().trim()) > Double
227                         .parseDouble(bSide.toString().trim())) {
228                         return 1;
229                     } else {
230                         return 0;
231                     }
232                 case OP_CODE_GTEQ:
233                     if (aSide == null || bSide == null) {
234                         return 0;
235                     }
236                     if (Double.parseDouble(aSide.toString().trim()) >= Double
237                         .parseDouble(bSide.toString().trim())) {
238                         return 1;
239                     } else {
240                         return 0;
241                     }
242
243                 case OP_CODE_LT:
244                     if (aSide == null || bSide == null) {
245                         return 0;
246                     }
247                     if (Double.parseDouble(aSide.toString().trim()) < Double
248                         .parseDouble(bSide.toString().trim())) {
249                         return 1;
250                     } else {
251                         return 0;
252                     }
253                 case OP_CODE_LTEQ:
254                     if (aSide == null || bSide == null) {
255                         return 0;
256                     }
257                     if (Double.parseDouble(aSide.toString().trim()) <= Double
258                         .parseDouble(bSide.toString().trim())) {
259                         return 1;
260                     } else {
261                         return 0;
262                     }
263             }
264         }
265
266         int leftResult = 0;
267         if (left != null) {
268             leftResult = left.checkValue(value);
269         }
270
271         int rightResult = 0;
272         if (right != null) {
273             rightResult = right.checkValue(value);
274         }
275
276         if (operation == OP_CODE_SKIP) {
277             if (rightResult == 0) {
278                 return 2;
279             } else {
280                 return 3;
281             }
282         }
283
284         if (operation == OP_CODE_AND) {
285             if (leftResult == 0) {
286                 return 0;
287             }
288             if (rightResult == 0) {
289                 return 0;
290             }
291             if (leftResult >= 2) {
292                 return leftResult;
293             }
294             if (rightResult >= 2) {
295                 return rightResult;
296             }
297
298             return 1;
299         }
300
301         if (operation == OP_CODE_OR) {
302             if (leftResult == 0 && rightResult == 0) {
303                 return 0;
304             }
305             if (leftResult >= 2) {
306                 return leftResult;
307             }
308             if (rightResult >= 2) {
309                 return rightResult;
310             }
311             return 1;
312         }
313
314         return 0;
315     }
316
317     public String toString() {
318         return criteria;
319     }
320
321     public String getCriteriaForProperty(XSQLColumn col) {
322         StringBuffer result = new StringBuffer();
323         if (criteria == null) {
324             return "";
325         }
326
327         if (leftValue != null && rightValue != null) {
328             if (leftValue.toString().toLowerCase().equals(col.getName().toLowerCase()) ||
329                 leftValue.toString().toLowerCase().equals(col.toString().toLowerCase()) /*||
330                 /*col.getName().toLowerCase().indexOf(leftValue.toString().toLowerCase()) != -1*/) {
331                 result.append("? ").append(operators[operation]).append(" ").append(rightValue);
332             }else
333             if (rightValue.toString().toLowerCase().equals(col.getName().toLowerCase()) ||
334                     rightValue.toString().toLowerCase().equals(col.toString().toLowerCase()) /*||
335                     col.getName().toLowerCase().indexOf(rightValue.toString().toLowerCase()) != -1*/) {
336                     result.append("? ").append(operators[operation]).append(" ").append(leftValue);
337             }
338             return result.toString();
339         } else if (left != null && right != null) {
340             String leftString = left.getCriteriaForProperty(col);
341             String rightString = right.getCriteriaForProperty(col);
342             if (!leftString.equals("") && !rightString.equals("")) {
343                 return leftString + " " + operators[operation] + " "
344                     + rightString;
345             } else if (!leftString.equals("")) {
346                 return leftString;
347             } else if (!rightString.equals("")) {
348                 return rightString;
349             }
350             return "";
351         } else if (leftValue != null && leftValue.toString().toLowerCase()
352             .equals(col.toString().toLowerCase()) && right != null) {
353             return "? " + operators[operation] + " (" + right
354                 .getCriteriaForProperty(col) + ")";
355         } else if (rightValue != null && rightValue.toString().toLowerCase()
356             .equals(col.toString().toLowerCase()) && left != null) {
357             return "(" + left.getCriteriaForProperty(col) + ") "
358                 + operators[operation] + " ?";
359         }
360         return "";
361     }
362
363     public static void main(String args[]) {
364         XSQLCriteria p =
365             new XSQLCriteria("ip like '%101%' or (354>=0 or 456>=3)", -1);
366         System.out.println(p.checkValue("192.268.4.4"));
367         p = new XSQLCriteria("? like '%267%'", -1);
368         System.out.println(p.checkValue("192.268.4.4"));
369
370     }
371 }