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      * Equal-strict operator.
149      * <br><strong>Syntax:</strong> <code>x === y</code>
150      * <br><strong>Method:</strong> <code>boolean strictEquals(L x, R y);</code>.
151      * @see JexlArithmetic#strictEquals(Object, Object)
152      */
153     EQSTRICT("===", "strictEquals", 2),
154 
155     /**
156      * Less-than operator.
157      * <br><strong>Syntax:</strong> <code>x &lt; y</code>
158      * <br><strong>Method:</strong> <code>boolean lessThan(L x, R y);</code>.
159      * @see JexlArithmetic#lessThan(Object, Object)
160      */
161     LT("<", "lessThan", 2),
162 
163     /**
164      * Less-than-or-equal operator.
165      * <br><strong>Syntax:</strong> <code>x &lt;= y</code>
166      * <br><strong>Method:</strong> <code>boolean lessThanOrEqual(L x, R y);</code>.
167      * @see JexlArithmetic#lessThanOrEqual(Object, Object)
168      */
169     LTE("<=", "lessThanOrEqual", 2),
170 
171     /**
172      * Greater-than operator.
173      * <br><strong>Syntax:</strong> <code>x &gt; y</code>
174      * <br><strong>Method:</strong> <code>boolean greaterThan(L x, R y);</code>.
175      * @see JexlArithmetic#greaterThan(Object, Object)
176      */
177     GT(">", "greaterThan", 2),
178 
179     /**
180      * Greater-than-or-equal operator.
181      * <br><strong>Syntax:</strong> <code>x &gt;= y</code>
182      * <br><strong>Method:</strong> <code>boolean greaterThanOrEqual(L x, R y);</code>.
183      * @see JexlArithmetic#greaterThanOrEqual(Object, Object)
184      */
185     GTE(">=", "greaterThanOrEqual", 2),
186 
187     /**
188      * Contains operator.
189      * <br><strong>Syntax:</strong> <code>x =~ y</code>
190      * <br><strong>Method:</strong> <code>boolean contains(L x, R y);</code>.
191      * @see JexlArithmetic#contains(Object, Object)
192      */
193     CONTAINS("=~", "contains", 2),
194 
195     /**
196      * Starts-with operator.
197      * <br><strong>Syntax:</strong> <code>x =^ y</code>
198      * <br><strong>Method:</strong> <code>boolean startsWith(L x, R y);</code>.
199      * @see JexlArithmetic#startsWith(Object, Object)
200      */
201     STARTSWITH("=^", "startsWith", 2),
202 
203     /**
204      * Ends-with operator.
205      * <br><strong>Syntax:</strong> <code>x =$ y</code>
206      * <br><strong>Method:</strong> <code>boolean endsWith(L x, R y);</code>.
207      * @see JexlArithmetic#endsWith(Object, Object)
208      */
209     ENDSWITH("=$", "endsWith", 2),
210 
211     /**
212      * Not operator.
213      * <br><strong>Syntax:</strong> <code>!x</code>
214      * <br><strong>Method:</strong> <code>T not(L x);</code>.
215      * @see JexlArithmetic#not(Object)
216      */
217     NOT("!", "not", 1),
218 
219     /**
220      * Complement operator.
221      * <br><strong>Syntax:</strong> <code>~x</code>
222      * <br><strong>Method:</strong> <code>T complement(L x);</code>.
223      * @see JexlArithmetic#complement(Object)
224      */
225     COMPLEMENT("~", "complement", 1),
226 
227     /**
228      * Negate operator.
229      * <br><strong>Syntax:</strong> <code>-x</code>
230      * <br><strong>Method:</strong> <code>T negate(L x);</code>.
231      * @see JexlArithmetic#negate(Object)
232      */
233     NEGATE("-", "negate", 1),
234 
235     /**
236      * Positivize operator.
237      * <br><strong>Syntax:</strong> <code>+x</code>
238      * <br><strong>Method:</strong> <code>T positivize(L x);</code>.
239      * @see JexlArithmetic#positivize(Object)
240      */
241     POSITIVIZE("+", "positivize", 1),
242 
243     /**
244      * Empty operator.
245      * <br><strong>Syntax:</strong> <code>empty x</code> or <code>empty(x)</code>
246      * <br><strong>Method:</strong> <code>boolean empty(L x);</code>.
247      * @see JexlArithmetic#empty(Object)
248      */
249     EMPTY("empty", "empty", 1),
250 
251     /**
252      * Size operator.
253      * <br><strong>Syntax:</strong> <code>size x</code> or <code>size(x)</code>
254      * <br><strong>Method:</strong> <code>int size(L x);</code>.
255      * @see JexlArithmetic#size(Object)
256      */
257     SIZE("size", "size", 1),
258 
259     /**
260      * Self-add operator.
261      * <br><strong>Syntax:</strong> <code>x += y</code>
262      * <br><strong>Method:</strong> <code>T selfAdd(L x, R y);</code>.
263      */
264     SELF_ADD("+=", "selfAdd", ADD),
265 
266     /**
267      * Self-subtract operator.
268      * <br><strong>Syntax:</strong> <code>x -= y</code>
269      * <br><strong>Method:</strong> <code>T selfSubtract(L x, R y);</code>.
270      */
271     SELF_SUBTRACT("-=", "selfSubtract", SUBTRACT),
272 
273     /**
274      * Self-multiply operator.
275      * <br><strong>Syntax:</strong> <code>x *= y</code>
276      * <br><strong>Method:</strong> <code>T selfMultiply(L x, R y);</code>.
277      */
278     SELF_MULTIPLY("*=", "selfMultiply", MULTIPLY),
279 
280     /**
281      * Self-divide operator.
282      * <br><strong>Syntax:</strong> <code>x /= y</code>
283      * <br><strong>Method:</strong> <code>T selfDivide(L x, R y);</code>.
284      */
285     SELF_DIVIDE("/=", "selfDivide", DIVIDE),
286 
287     /**
288      * Self-modulo operator.
289      * <br><strong>Syntax:</strong> <code>x %= y</code>
290      * <br><strong>Method:</strong> <code>T selfMod(L x, R y);</code>.
291      */
292     SELF_MOD("%=", "selfMod", MOD),
293 
294     /**
295      * Self-and operator.
296      * <br><strong>Syntax:</strong> <code>x &amp;= y</code>
297      * <br><strong>Method:</strong> <code>T selfAnd(L x, R y);</code>.
298      */
299     SELF_AND("&=", "selfAnd", AND),
300 
301     /**
302      * Self-or operator.
303      * <br><strong>Syntax:</strong> <code>x |= y</code>
304      * <br><strong>Method:</strong> <code>T selfOr(L x, R y);</code>.
305      */
306     SELF_OR("|=", "selfOr", OR),
307 
308     /**
309      * Self-xor operator.
310      * <br><strong>Syntax:</strong> <code>x ^= y</code>
311      * <br><strong>Method:</strong> <code>T selfXor(L x, R y);</code>.
312      */
313     SELF_XOR("^=", "selfXor", XOR),
314 
315     /**
316      * Self-right-shift operator.
317      * <br><strong>Syntax:</strong> <code>x &gt;&gt;= y</code>
318      * <br><strong>Method:</strong> <code>T selfShiftRight(L x, R y);</code>.
319      */
320     SELF_SHIFTRIGHT(">>=", "selfShiftRight", SHIFTRIGHT),
321 
322     /**
323      * Self-right-shift unsigned operator.
324      * <br><strong>Syntax:</strong> <code>x &gt;&gt;&gt; y</code>
325      * <br><strong>Method:</strong> <code>T selfShiftRightUnsigned(L x, R y);</code>.
326      */
327     SELF_SHIFTRIGHTU(">>>=", "selfShiftRightUnsigned", SHIFTRIGHTU),
328 
329     /**
330      * Self-left-shift operator.
331      * <br><strong>Syntax:</strong> <code>x &lt;&lt; y</code>
332      * <br><strong>Method:</strong> <code>T selfShiftLeft(L x, R y);</code>.
333      */
334     SELF_SHIFTLEFT("<<=", "selfShiftLeft", SHIFTLEFT),
335 
336     /**
337      * Increment pseudo-operator.
338      * <br>No syntax, used as helper for the prefix and postfix versions of <code>++</code>.
339      * @see JexlArithmetic#increment(Object)
340      */
341     INCREMENT("+1", "increment", 1),
342 
343     /**
344      * Decrement pseudo-operator.
345      * <br>No syntax, used as helper for the prefix and postfix versions of <code>--</code>.
346      * @see JexlArithmetic#decrement(Object)
347      */
348     DECREMENT("-1", "decrement", 1),
349 
350     /**
351      * Prefix ++ operator, increments and returns the value after incrementing.
352      * <br><strong>Syntax:</strong> <code>++x</code>
353      * <br><strong>Method:</strong> <code>T incrementAndGet(L x);</code>.
354      */
355     INCREMENT_AND_GET("++.", "incrementAndGet", INCREMENT, 1),
356 
357     /**
358      * Postfix ++, increments and returns the value before incrementing.
359      * <br><strong>Syntax:</strong> <code>x++</code>
360      * <br><strong>Method:</strong> <code>T getAndIncrement(L x);</code>.
361      */
362     GET_AND_INCREMENT(".++", "getAndIncrement", INCREMENT, 1),
363 
364     /**
365      * Prefix --, decrements and returns the value after decrementing.
366      * <br><strong>Syntax:</strong> <code>--x</code>
367      * <br><strong>Method:</strong> <code>T decrementAndGet(L x);</code>.
368      */
369     DECREMENT_AND_GET("--.", "decrementAndGet", DECREMENT, 1),
370 
371     /**
372      * Postfix --, decrements and returns the value before decrementing.
373      * <br><strong>Syntax:</strong> <code>x--</code>
374      * <br><strong>Method:</strong> <code>T getAndDecrement(L x);</code>.
375      */
376     GET_AND_DECREMENT(".--", "getAndDecrement", DECREMENT, 1),
377 
378     /**
379      * Marker for side effect.
380      * <br>Returns this from 'self*' overload method to let the engine know the side effect has been performed and
381      * there is no need to assign the result.
382      */
383     ASSIGN("=", null, null),
384 
385     /**
386      * Property get operator as in: x.y.
387      * <br><strong>Syntax:</strong> <code>x.y</code>
388      * <br><strong>Method:</strong> <code>Object propertyGet(L x, R y);</code>.
389      */
390     PROPERTY_GET(".", "propertyGet", 2),
391 
392     /**
393      * Property set operator as in: x.y = z.
394      * <br><strong>Syntax:</strong> <code>x.y = z</code>
395      * <br><strong>Method:</strong> <code>void propertySet(L x, R y, V z);</code>.
396      */
397     PROPERTY_SET(".=", "propertySet", 3),
398 
399     /**
400      * Array get operator as in: x[y].
401      * <br><strong>Syntax:</strong> <code>x.y</code>
402      * <br><strong>Method:</strong> <code>Object arrayGet(L x, R y);</code>.
403      */
404     ARRAY_GET("[]", "arrayGet", 2),
405 
406     /**
407      * Array set operator as in: x[y] = z.
408      * <br><strong>Syntax:</strong> <code>x[y] = z</code>
409      * <br><strong>Method:</strong> <code>void arraySet(L x, R y, V z);</code>.
410      */
411     ARRAY_SET("[]=", "arraySet", 3),
412 
413     /**
414      * Iterator generator as in for(var x : y).
415      * If the returned Iterator is AutoCloseable, close will be called after the last execution of the loop block.
416      * <br><strong>Syntax:</strong> <code>for(var x : y){...} </code>
417      * <br><strong>Method:</strong> <code>Iterator&lt;Object&gt; forEach(R y);</code>.
418      * @since 3.1
419      */
420     FOR_EACH("for(...)", "forEach", 1),
421 
422     /**
423      * Test condition in if, for, while.
424      * <br><strong>Method:</strong> <code>boolean testCondition(R y);</code>.
425      * @since 3.3
426      */
427     CONDITION("?", "testCondition", 1);
428 
429     /**
430      * The operator symbol.
431      */
432     private final String operator;
433 
434     /**
435      * The associated operator method name.
436      */
437     private final String methodName;
438 
439     /**
440      * The method arity (ie number of arguments).
441      */
442     private final int arity;
443 
444     /**
445      * The base operator.
446      */
447     private final JexlOperator base;
448 
449     /**
450      * Creates a base operator.
451      *
452      * @param o    the operator name
453      * @param m    the method name associated to this operator in a JexlArithmetic
454      * @param argc the number of parameters for the method
455      */
456     JexlOperator(final String o, final String m, final int argc) {
457         this(o, m, null, argc);
458     }
459 
460     /**
461      * Creates a side effect operator with arity == 2.
462      *
463      * @param o the operator name
464      * @param m the method name associated to this operator in a JexlArithmetic
465      * @param b the base operator, ie + for +=
466      */
467     JexlOperator(final String o, final String m, final JexlOperator b) {
468         this(o, m, b, 2);
469     }
470 
471     /**
472      * Creates a side effect operator.
473      *
474      * @param o the operator name
475      * @param m the method name associated to this operator in a JexlArithmetic
476      * @param b the base operator, ie + for +=
477      * @param a the operator arity
478      */
479     JexlOperator(final String o, final String m, final JexlOperator b, final int a) {
480         this.operator = o;
481         this.methodName = m;
482         this.arity = a;
483         this.base = b;
484     }
485 
486     /**
487      * Gets this operator number of parameters.
488      *
489      * @return the method arity
490      */
491     public int getArity() {
492         return arity;
493     }
494 
495     /**
496      * Gets the base operator.
497      *
498      * @return the base operator
499      */
500     public final JexlOperator getBaseOperator() {
501         return base;
502     }
503 
504     /**
505      * Gets this operator method name in a JexlArithmetic.
506      *
507      * @return the method name
508      */
509     public final String getMethodName() {
510         return methodName;
511     }
512 
513     /**
514      * Gets this operator symbol.
515      *
516      * @return the symbol
517      */
518     public final String getOperatorSymbol() {
519         return operator;
520     }
521 
522 }