View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.jexl3;
19  
20  /**
21   * The JEXL operators.
22   *
23   * These are the operators that are executed by JexlArithmetic methods.
24   *
25   * <p>Each of them  associates a symbol to a method signature.
26   * For instance, '+' is associated to 'T add(L x, R y)'.</p>
27   *
28   * <p>The default JexlArithmetic implements generic versions of these methods using Object as arguments.
29   * You can use your own derived JexlArithmetic that override and/or overload those operator methods.
30   * Note that these are overloads by convention, not actual Java overloads.
31   * The following rules apply to all operator methods:</p>
32   * <ul>
33   * <li>Operator methods should be public</li>
34   * <li>Operators return type should be respected when primitive (int, boolean,...)</li>
35   * <li>Operators may be overloaded multiple times with different signatures</li>
36   * <li>Operators may return JexlEngine.TRY_AGAIN to fallback on default JEXL implementation</li>
37   * </ul>
38   *
39   * For side effect operators, operators that modify the left-hand size value (+=, -=, etc), the user implemented
40   * overload methods may return:
41   * <ul>
42   *     <li>JexlEngine.TRY_FAIL to let the default fallback behavior be executed.</li>
43   *     <li>Any other value will be used as the new value to be assigned to the left-hand-side.</li>
44   * </ul>
45   * Note that side effect operators always return the left-hand side value (with an exception for postfix ++ and --).
46   *
47   * @since 3.0
48   */
49  public enum JexlOperator {
50  
51      /**
52       * Add operator.
53       * <br><strong>Syntax:</strong> <code>x + y</code>
54       * <br><strong>Method:</strong> <code>T add(L x, R y);</code>.
55       * @see JexlArithmetic#add(Object, Object)
56       */
57      ADD("+", "add", 2),
58  
59      /**
60       * Subtract operator.
61       * <br><strong>Syntax:</strong> <code>x - y</code>
62       * <br><strong>Method:</strong> <code>T subtract(L x, R y);</code>.
63       * @see JexlArithmetic#subtract(Object, Object)
64       */
65      SUBTRACT("-", "subtract", 2),
66  
67      /**
68       * Multiply operator.
69       * <br><strong>Syntax:</strong> <code>x * y</code>
70       * <br><strong>Method:</strong> <code>T multiply(L x, R y);</code>.
71       * @see JexlArithmetic#multiply(Object, Object)
72       */
73      MULTIPLY("*", "multiply", 2),
74  
75      /**
76       * Divide operator.
77       * <br><strong>Syntax:</strong> <code>x / y</code>
78       * <br><strong>Method:</strong> <code>T divide(L x, R y);</code>.
79       * @see JexlArithmetic#divide(Object, Object)
80       */
81      DIVIDE("/", "divide", 2),
82  
83      /**
84       * Modulo operator.
85       * <br><strong>Syntax:</strong> <code>x % y</code>
86       * <br><strong>Method:</strong> <code>T mod(L x, R y);</code>.
87       * @see JexlArithmetic#mod(Object, Object)
88       */
89      MOD("%", "mod", 2),
90  
91      /**
92       * Bitwise-and operator.
93       * <br><strong>Syntax:</strong> <code>x &amp; y</code>
94       * <br><strong>Method:</strong> <code>T and(L x, R y);</code>.
95       * @see JexlArithmetic#and(Object, Object)
96       */
97      AND("&", "and", 2),
98  
99      /**
100      * Bitwise-or operator.
101      * <br><strong>Syntax:</strong> <code>x | y</code>
102      * <br><strong>Method:</strong> <code>T or(L x, R y);</code>.
103      * @see JexlArithmetic#or(Object, Object)
104      */
105     OR("|", "or", 2),
106 
107     /**
108      * Bitwise-xor operator.
109      * <br><strong>Syntax:</strong> <code>x ^ y</code>
110      * <br><strong>Method:</strong> <code>T xor(L x, R y);</code>.
111      * @see JexlArithmetic#xor(Object, Object)
112      */
113     XOR("^", "xor", 2),
114 
115     /**
116      * Bit-pattern right-shift operator.
117      * <br><strong>Syntax:</strong> <code>x &gt;&gt; y</code>
118      * <br><strong>Method:</strong> <code>T rightShift(L x, R y);</code>.
119      * @see JexlArithmetic#shiftRight(Object, Object)
120      */
121     SHIFTRIGHT(">>", "shiftRight", 2),
122 
123     /**
124      * Bit-pattern right-shift unsigned operator.
125      * <br><strong>Syntax:</strong> <code>x &gt;&gt;&gt; y</code>
126      * <br><strong>Method:</strong> <code>T rightShiftUnsigned(L x, R y);</code>.
127      * @see JexlArithmetic#shiftRightUnsigned(Object, Object)
128      */
129     SHIFTRIGHTU(">>>", "shiftRightUnsigned", 2),
130 
131     /**
132      * Bit-pattern left-shift operator.
133      * <br><strong>Syntax:</strong> <code>x &lt;&lt; y</code>
134      * <br><strong>Method:</strong> <code>T leftShift(L x, R y);</code>.
135      * @see JexlArithmetic#shiftLeft(Object, Object)
136      */
137     SHIFTLEFT("<<", "shiftLeft", 2),
138 
139     /**
140      * Equals operator.
141      * <br><strong>Syntax:</strong> <code>x == y</code>
142      * <br><strong>Method:</strong> <code>boolean equals(L x, R y);</code>.
143      * @see JexlArithmetic#equals(Object, Object)
144      */
145     EQ("==", "equals", 2),
146 
147     /**
148      * Less-than operator.
149      * <br><strong>Syntax:</strong> <code>x &lt; y</code>
150      * <br><strong>Method:</strong> <code>boolean lessThan(L x, R y);</code>.
151      * @see JexlArithmetic#lessThan(Object, Object)
152      */
153     LT("<", "lessThan", 2),
154 
155     /**
156      * Less-than-or-equal operator.
157      * <br><strong>Syntax:</strong> <code>x &lt;= y</code>
158      * <br><strong>Method:</strong> <code>boolean lessThanOrEqual(L x, R y);</code>.
159      * @see JexlArithmetic#lessThanOrEqual(Object, Object)
160      */
161     LTE("<=", "lessThanOrEqual", 2),
162 
163     /**
164      * Greater-than operator.
165      * <br><strong>Syntax:</strong> <code>x &gt; y</code>
166      * <br><strong>Method:</strong> <code>boolean greaterThan(L x, R y);</code>.
167      * @see JexlArithmetic#greaterThan(Object, Object)
168      */
169     GT(">", "greaterThan", 2),
170 
171     /**
172      * Greater-than-or-equal operator.
173      * <br><strong>Syntax:</strong> <code>x &gt;= y</code>
174      * <br><strong>Method:</strong> <code>boolean greaterThanOrEqual(L x, R y);</code>.
175      * @see JexlArithmetic#greaterThanOrEqual(Object, Object)
176      */
177     GTE(">=", "greaterThanOrEqual", 2),
178 
179     /**
180      * Contains operator.
181      * <br><strong>Syntax:</strong> <code>x =~ y</code>
182      * <br><strong>Method:</strong> <code>boolean contains(L x, R y);</code>.
183      * @see JexlArithmetic#contains(Object, Object)
184      */
185     CONTAINS("=~", "contains", 2),
186 
187     /**
188      * Starts-with operator.
189      * <br><strong>Syntax:</strong> <code>x =^ y</code>
190      * <br><strong>Method:</strong> <code>boolean startsWith(L x, R y);</code>.
191      * @see JexlArithmetic#startsWith(Object, Object)
192      */
193     STARTSWITH("=^", "startsWith", 2),
194 
195     /**
196      * Ends-with operator.
197      * <br><strong>Syntax:</strong> <code>x =$ y</code>
198      * <br><strong>Method:</strong> <code>boolean endsWith(L x, R y);</code>.
199      * @see JexlArithmetic#endsWith(Object, Object)
200      */
201     ENDSWITH("=$", "endsWith", 2),
202 
203     /**
204      * Not operator.
205      * <br><strong>Syntax:</strong> <code>!x</code>
206      * <br><strong>Method:</strong> <code>T not(L x);</code>.
207      * @see JexlArithmetic#not(Object)
208      */
209     NOT("!", "not", 1),
210 
211     /**
212      * Complement operator.
213      * <br><strong>Syntax:</strong> <code>~x</code>
214      * <br><strong>Method:</strong> <code>T complement(L x);</code>.
215      * @see JexlArithmetic#complement(Object)
216      */
217     COMPLEMENT("~", "complement", 1),
218 
219     /**
220      * Negate operator.
221      * <br><strong>Syntax:</strong> <code>-x</code>
222      * <br><strong>Method:</strong> <code>T negate(L x);</code>.
223      * @see JexlArithmetic#negate(Object)
224      */
225     NEGATE("-", "negate", 1),
226 
227     /**
228      * Positivize operator.
229      * <br><strong>Syntax:</strong> <code>+x</code>
230      * <br><strong>Method:</strong> <code>T positivize(L x);</code>.
231      * @see JexlArithmetic#positivize(Object)
232      */
233     POSITIVIZE("+", "positivize", 1),
234 
235     /**
236      * Empty operator.
237      * <br><strong>Syntax:</strong> <code>empty x</code> or <code>empty(x)</code>
238      * <br><strong>Method:</strong> <code>boolean empty(L x);</code>.
239      * @see JexlArithmetic#empty(Object)
240      */
241     EMPTY("empty", "empty", 1),
242 
243     /**
244      * Size operator.
245      * <br><strong>Syntax:</strong> <code>size x</code> or <code>size(x)</code>
246      * <br><strong>Method:</strong> <code>int size(L x);</code>.
247      * @see JexlArithmetic#size(Object)
248      */
249     SIZE("size", "size", 1),
250 
251     /**
252      * Self-add operator.
253      * <br><strong>Syntax:</strong> <code>x += y</code>
254      * <br><strong>Method:</strong> <code>T selfAdd(L x, R y);</code>.
255      */
256     SELF_ADD("+=", "selfAdd", ADD),
257 
258     /**
259      * Self-subtract operator.
260      * <br><strong>Syntax:</strong> <code>x -= y</code>
261      * <br><strong>Method:</strong> <code>T selfSubtract(L x, R y);</code>.
262      */
263     SELF_SUBTRACT("-=", "selfSubtract", SUBTRACT),
264 
265     /**
266      * Self-multiply operator.
267      * <br><strong>Syntax:</strong> <code>x *= y</code>
268      * <br><strong>Method:</strong> <code>T selfMultiply(L x, R y);</code>.
269      */
270     SELF_MULTIPLY("*=", "selfMultiply", MULTIPLY),
271 
272     /**
273      * Self-divide operator.
274      * <br><strong>Syntax:</strong> <code>x /= y</code>
275      * <br><strong>Method:</strong> <code>T selfDivide(L x, R y);</code>.
276      */
277     SELF_DIVIDE("/=", "selfDivide", DIVIDE),
278 
279     /**
280      * Self-modulo operator.
281      * <br><strong>Syntax:</strong> <code>x %= y</code>
282      * <br><strong>Method:</strong> <code>T selfMod(L x, R y);</code>.
283      */
284     SELF_MOD("%=", "selfMod", MOD),
285 
286     /**
287      * Self-and operator.
288      * <br><strong>Syntax:</strong> <code>x &amp;= y</code>
289      * <br><strong>Method:</strong> <code>T selfAnd(L x, R y);</code>.
290      */
291     SELF_AND("&=", "selfAnd", AND),
292 
293     /**
294      * Self-or operator.
295      * <br><strong>Syntax:</strong> <code>x |= y</code>
296      * <br><strong>Method:</strong> <code>T selfOr(L x, R y);</code>.
297      */
298     SELF_OR("|=", "selfOr", OR),
299 
300     /**
301      * Self-xor operator.
302      * <br><strong>Syntax:</strong> <code>x ^= y</code>
303      * <br><strong>Method:</strong> <code>T selfXor(L x, R y);</code>.
304      */
305     SELF_XOR("^=", "selfXor", XOR),
306 
307     /**
308      * Self-right-shift operator.
309      * <br><strong>Syntax:</strong> <code>x &gt;&gt;= y</code>
310      * <br><strong>Method:</strong> <code>T selfShiftRight(L x, R y);</code>.
311      */
312     SELF_SHIFTRIGHT(">>=", "selfShiftRight", SHIFTRIGHT),
313 
314     /**
315      * Self-right-shift unsigned operator.
316      * <br><strong>Syntax:</strong> <code>x &gt;&gt;&gt; y</code>
317      * <br><strong>Method:</strong> <code>T selfShiftRightUnsigned(L x, R y);</code>.
318      */
319     SELF_SHIFTRIGHTU(">>>=", "selfShiftRightUnsigned", SHIFTRIGHTU),
320 
321     /**
322      * Self-left-shift operator.
323      * <br><strong>Syntax:</strong> <code>x &lt;&lt; y</code>
324      * <br><strong>Method:</strong> <code>T selfShiftLeft(L x, R y);</code>.
325      */
326     SELF_SHIFTLEFT("<<=", "selfShiftLeft", SHIFTLEFT),
327 
328     /**
329      * Increment pseudo-operator.
330      * <br>No syntax, used as helper for the prefix and postfix versions of <code>++</code>.
331      * @see JexlArithmetic#increment(Object)
332      */
333     INCREMENT("+1", "increment", 1),
334 
335     /**
336      * Decrement pseudo-operator.
337      * <br>No syntax, used as helper for the prefix and postfix versions of <code>--</code>.
338      * @see JexlArithmetic#decrement(Object)
339      */
340     DECREMENT("-1", "decrement", 1),
341 
342     /**
343      * Prefix ++ operator, increments and returns the value after incrementing.
344      * <br><strong>Syntax:</strong> <code>++x</code>
345      * <br><strong>Method:</strong> <code>T incrementAndGet(L x);</code>.
346      */
347     INCREMENT_AND_GET("++.", "incrementAndGet", INCREMENT, 1),
348 
349     /**
350      * Postfix ++, increments and returns the value before incrementing.
351      * <br><strong>Syntax:</strong> <code>x++</code>
352      * <br><strong>Method:</strong> <code>T getAndIncrement(L x);</code>.
353      */
354     GET_AND_INCREMENT(".++", "getAndIncrement", INCREMENT, 1),
355 
356     /**
357      * Prefix --, decrements and returns the value after decrementing.
358      * <br><strong>Syntax:</strong> <code>--x</code>
359      * <br><strong>Method:</strong> <code>T decrementAndGet(L x);</code>.
360      */
361     DECREMENT_AND_GET("--.", "decrementAndGet", DECREMENT, 1),
362 
363     /**
364      * Postfix --, decrements and returns the value before decrementing.
365      * <br><strong>Syntax:</strong> <code>x--</code>
366      * <br><strong>Method:</strong> <code>T getAndDecrement(L x);</code>.
367      */
368     GET_AND_DECREMENT(".--", "getAndDecrement", DECREMENT, 1),
369 
370     /**
371      * Marker for side effect.
372      * <br>Returns this from 'self*' overload method to let the engine know the side effect has been performed and
373      * there is no need to assign the result.
374      */
375     ASSIGN("=", null, null),
376 
377     /**
378      * Property get operator as in: x.y.
379      * <br><strong>Syntax:</strong> <code>x.y</code>
380      * <br><strong>Method:</strong> <code>Object propertyGet(L x, R y);</code>.
381      */
382     PROPERTY_GET(".", "propertyGet", 2),
383 
384     /**
385      * Property set operator as in: x.y = z.
386      * <br><strong>Syntax:</strong> <code>x.y = z</code>
387      * <br><strong>Method:</strong> <code>void propertySet(L x, R y, V z);</code>.
388      */
389     PROPERTY_SET(".=", "propertySet", 3),
390 
391     /**
392      * Array get operator as in: x[y].
393      * <br><strong>Syntax:</strong> <code>x.y</code>
394      * <br><strong>Method:</strong> <code>Object arrayGet(L x, R y);</code>.
395      */
396     ARRAY_GET("[]", "arrayGet", 2),
397 
398     /**
399      * Array set operator as in: x[y] = z.
400      * <br><strong>Syntax:</strong> <code>x[y] = z</code>
401      * <br><strong>Method:</strong> <code>void arraySet(L x, R y, V z);</code>.
402      */
403     ARRAY_SET("[]=", "arraySet", 3),
404 
405     /**
406      * Iterator generator as in for(var x : y).
407      * If the returned Iterator is AutoCloseable, close will be called after the last execution of the loop block.
408      * <br><strong>Syntax:</strong> <code>for(var x : y){...} </code>
409      * <br><strong>Method:</strong> <code>Iterator&lt;Object&gt; forEach(R y);</code>.
410      * @since 3.1
411      */
412     FOR_EACH("for(...)", "forEach", 1),
413 
414     /**
415      * Test condition in if, for, while.
416      * <br><strong>Method:</strong> <code>boolean testCondition(R y);</code>.
417      * @since 3.3
418      */
419     CONDITION("?", "testCondition", 1);
420 
421     /**
422      * The operator symbol.
423      */
424     private final String operator;
425 
426     /**
427      * The associated operator method name.
428      */
429     private final String methodName;
430 
431     /**
432      * The method arity (ie number of arguments).
433      */
434     private final int arity;
435 
436     /**
437      * The base operator.
438      */
439     private final JexlOperator base;
440 
441     /**
442      * Creates a base operator.
443      *
444      * @param o    the operator name
445      * @param m    the method name associated to this operator in a JexlArithmetic
446      * @param argc the number of parameters for the method
447      */
448     JexlOperator(final String o, final String m, final int argc) {
449         this(o, m, null, argc);
450     }
451 
452     /**
453      * Creates a side effect operator with arity == 2.
454      *
455      * @param o the operator name
456      * @param m the method name associated to this operator in a JexlArithmetic
457      * @param b the base operator, ie + for +=
458      */
459     JexlOperator(final String o, final String m, final JexlOperator b) {
460         this(o, m, b, 2);
461     }
462 
463     /**
464      * Creates a side effect operator.
465      *
466      * @param o the operator name
467      * @param m the method name associated to this operator in a JexlArithmetic
468      * @param b the base operator, ie + for +=
469      * @param a the operator arity
470      */
471     JexlOperator(final String o, final String m, final JexlOperator b, final int a) {
472         this.operator = o;
473         this.methodName = m;
474         this.arity = a;
475         this.base = b;
476     }
477 
478     /**
479      * Gets this operator symbol.
480      *
481      * @return the symbol
482      */
483     public final String getOperatorSymbol() {
484         return operator;
485     }
486 
487     /**
488      * Gets this operator method name in a JexlArithmetic.
489      *
490      * @return the method name
491      */
492     public final String getMethodName() {
493         return methodName;
494     }
495 
496     /**
497      * Gets this operator number of parameters.
498      *
499      * @return the method arity
500      */
501     public int getArity() {
502         return arity;
503     }
504 
505     /**
506      * Gets the base operator.
507      *
508      * @return the base operator
509      */
510     public final JexlOperator getBaseOperator() {
511         return base;
512     }
513 
514 }