001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.jexl3;
019
020/**
021 * The JEXL operators.
022 *
023 * These are the operators that are executed by JexlArithmetic methods.
024 *
025 * <p>Each of them  associates a symbol to a method signature.
026 * For instance, '+' is associated to 'T add(L x, R y)'.</p>
027 *
028 * <p>The default JexlArithmetic implements generic versions of these methods using Object as arguments.
029 * You can use your own derived JexlArithmetic that override and/or overload those operator methods.
030 * Note that these are overloads by convention, not actual Java overloads.
031 * The following rules apply to operator methods:</p>
032 * <ul>
033 * <li>Operator methods should be public</li>
034 * <li>Operators return type should be respected when primitive (int, boolean,...)</li>
035 * <li>Operators may be overloaded multiple times with different signatures</li>
036 * <li>Operators may return JexlEngine.TRY_AGAIN to fallback on default JEXL implementation</li>
037 * </ul>
038 *
039 * @since 3.0
040 */
041public enum JexlOperator {
042
043    /**
044     * Add operator.
045     * <br><strong>Syntax:</strong> <code>x + y</code>
046     * <br><strong>Method:</strong> <code>T add(L x, R y);</code>.
047     * @see JexlArithmetic#add
048     */
049    ADD("+", "add", 2),
050
051    /**
052     * Subtract operator.
053     * <br><strong>Syntax:</strong> <code>x - y</code>
054     * <br><strong>Method:</strong> <code>T subtract(L x, R y);</code>.
055     * @see JexlArithmetic#subtract
056     */
057    SUBTRACT("-", "subtract", 2),
058
059    /**
060     * Multiply operator.
061     * <br><strong>Syntax:</strong> <code>x * y</code>
062     * <br><strong>Method:</strong> <code>T multiply(L x, R y);</code>.
063     * @see JexlArithmetic#multiply
064     */
065    MULTIPLY("*", "multiply", 2),
066
067    /**
068     * Divide operator.
069     * <br><strong>Syntax:</strong> <code>x / y</code>
070     * <br><strong>Method:</strong> <code>T divide(L x, R y);</code>.
071     * @see JexlArithmetic#divide
072     */
073    DIVIDE("/", "divide", 2),
074
075    /**
076     * Modulo operator.
077     * <br><strong>Syntax:</strong> <code>x % y</code>
078     * <br><strong>Method:</strong> <code>T mod(L x, R y);</code>.
079     * @see JexlArithmetic#mod
080     */
081    MOD("%", "mod", 2),
082
083    /**
084     * Bitwise-and operator.
085     * <br><strong>Syntax:</strong> <code>x &amp; y</code>
086     * <br><strong>Method:</strong> <code>T and(L x, R y);</code>.
087     * @see JexlArithmetic#and
088     */
089    AND("&", "and", 2),
090
091    /**
092     * Bitwise-or operator.
093     * <br><strong>Syntax:</strong> <code>x | y</code>
094     * <br><strong>Method:</strong> <code>T or(L x, R y);</code>.
095     * @see JexlArithmetic#or
096     */
097    OR("|", "or", 2),
098
099    /**
100     * Bitwise-xor operator.
101     * <br><strong>Syntax:</strong> <code>x ^ y</code>
102     * <br><strong>Method:</strong> <code>T xor(L x, R y);</code>.
103     * @see JexlArithmetic#xor
104     */
105    XOR("^", "xor", 2),
106
107    /**
108     * Equals operator.
109     * <br><strong>Syntax:</strong> <code>x == y</code>
110     * <br><strong>Method:</strong> <code>boolean equals(L x, R y);</code>.
111     * @see JexlArithmetic#equals
112     */
113    EQ("==", "equals", 2),
114
115    /**
116     * Less-than operator.
117     * <br><strong>Syntax:</strong> <code>x &lt; y</code>
118     * <br><strong>Method:</strong> <code>boolean lessThan(L x, R y);</code>.
119     * @see JexlArithmetic#lessThan
120     */
121    LT("<", "lessThan", 2),
122
123    /**
124     * Less-than-or-equal operator.
125     * <br><strong>Syntax:</strong> <code>x &lt;= y</code>
126     * <br><strong>Method:</strong> <code>boolean lessThanOrEqual(L x, R y);</code>.
127     * @see JexlArithmetic#lessThanOrEqual
128     */
129    LTE("<=", "lessThanOrEqual", 2),
130
131    /**
132     * Greater-than operator.
133     * <br><strong>Syntax:</strong> <code>x &gt; y</code>
134     * <br><strong>Method:</strong> <code>boolean greaterThan(L x, R y);</code>.
135     * @see JexlArithmetic#greaterThan
136     */
137    GT(">", "greaterThan", 2),
138
139    /**
140     * Greater-than-or-equal operator.
141     * <br><strong>Syntax:</strong> <code>x &gt;= y</code>
142     * <br><strong>Method:</strong> <code>boolean greaterThanOrEqual(L x, R y);</code>.
143     * @see JexlArithmetic#greaterThanOrEqual
144     */
145    GTE(">=", "greaterThanOrEqual", 2),
146
147    /**
148     * Contains operator.
149     * <br><strong>Syntax:</strong> <code>x =~ y</code>
150     * <br><strong>Method:</strong> <code>boolean contains(L x, R y);</code>.
151     * @see JexlArithmetic#contains
152     */
153    CONTAINS("=~", "contains", 2),
154
155    /**
156     * Starts-with operator.
157     * <br><strong>Syntax:</strong> <code>x =^ y</code>
158     * <br><strong>Method:</strong> <code>boolean startsWith(L x, R y);</code>.
159     * @see JexlArithmetic#startsWith
160     */
161    STARTSWITH("=^", "startsWith", 2),
162
163    /**
164     * Ends-with operator.
165     * <br><strong>Syntax:</strong> <code>x =$ y</code>
166     * <br><strong>Method:</strong> <code>boolean endsWith(L x, R y);</code>.
167     * @see JexlArithmetic#endsWith
168     */
169    ENDSWITH("=$", "endsWith", 2),
170
171    /**
172     * Not operator.
173     * <br><strong>Syntax:</strong> <code>!x</code>
174     * <br><strong>Method:</strong> <code>T not(L x);</code>.
175     * @see JexlArithmetic#not
176     */
177    NOT("!", "not", 1),
178
179    /**
180     * Complement operator.
181     * <br><strong>Syntax:</strong> <code>~x</code>
182     * <br><strong>Method:</strong> <code>T complement(L x);</code>.
183     * @see JexlArithmetic#complement
184     */
185    COMPLEMENT("~", "complement", 1),
186
187    /**
188     * Negate operator.
189     * <br><strong>Syntax:</strong> <code>-x</code>
190     * <br><strong>Method:</strong> <code>T negate(L x);</code>.
191     * @see JexlArithmetic#negate
192     */
193    NEGATE("-", "negate", 1),
194
195    /**
196     * Positivize operator.
197     * <br><strong>Syntax:</strong> <code>+x</code>
198     * <br><strong>Method:</strong> <code>T positivize(L x);</code>.
199     * @see JexlArithmetic#positivize
200     */
201    POSITIVIZE("+", "positivize", 1),
202
203    /**
204     * Empty operator.
205     * <br><strong>Syntax:</strong> <code>empty x</code> or <code>empty(x)</code>
206     * <br><strong>Method:</strong> <code>boolean empty(L x);</code>.
207     * @see JexlArithmetic#empty
208     */
209    EMPTY("empty", "empty", 1),
210
211    /**
212     * Size operator.
213     * <br><strong>Syntax:</strong> <code>size x</code> or <code>size(x)</code>
214     * <br><strong>Method:</strong> <code>int size(L x);</code>.
215     * @see JexlArithmetic#size
216     */
217    SIZE("size", "size", 1),
218
219    /**
220     * Self-add operator.
221     * <br><strong>Syntax:</strong> <code>x += y</code>
222     * <br><strong>Method:</strong> <code>T selfAdd(L x, R y);</code>.
223     */
224    SELF_ADD("+=", "selfAdd", ADD),
225
226    /**
227     * Self-subtract operator.
228     * <br><strong>Syntax:</strong> <code>x -= y</code>
229     * <br><strong>Method:</strong> <code>T selfSubtract(L x, R y);</code>.
230     */
231    SELF_SUBTRACT("-=", "selfSubtract", SUBTRACT),
232
233    /**
234     * Self-multiply operator.
235     * <br><strong>Syntax:</strong> <code>x *= y</code>
236     * <br><strong>Method:</strong> <code>T selfMultiply(L x, R y);</code>.
237     */
238    SELF_MULTIPLY("*=", "selfMultiply", MULTIPLY),
239
240    /**
241     * Self-divide operator.
242     * <br><strong>Syntax:</strong> <code>x /= y</code>
243     * <br><strong>Method:</strong> <code>T selfDivide(L x, R y);</code>.
244     */
245    SELF_DIVIDE("/=", "selfDivide", DIVIDE),
246
247    /**
248     * Self-modulo operator.
249     * <br><strong>Syntax:</strong> <code>x %= y</code>
250     * <br><strong>Method:</strong> <code>T selfMod(L x, R y);</code>.
251     */
252    SELF_MOD("%=", "selfMod", MOD),
253
254    /**
255     * Self-and operator.
256     * <br><strong>Syntax:</strong> <code>x &amp;= y</code>
257     * <br><strong>Method:</strong> <code>T selfAnd(L x, R y);</code>.
258     */
259    SELF_AND("&=", "selfAnd", AND),
260
261    /**
262     * Self-or operator.
263     * <br><strong>Syntax:</strong> <code>x |= y</code>
264     * <br><strong>Method:</strong> <code>T selfOr(L x, R y);</code>.
265     */
266    SELF_OR("|=", "selfOr", OR),
267
268    /**
269     * Self-xor operator.
270     * <br><strong>Syntax:</strong> <code>x ^= y</code>
271     * <br><strong>Method:</strong> <code>T selfXor(L x, R y);</code>.
272     */
273    SELF_XOR("^=", "selfXor", XOR),
274
275    /**
276     * Marker for side effect.
277     * <br>Returns this from 'self*' overload method to let the engine know the side effect has been performed and
278     * there is no need to assign the result.
279     */
280    ASSIGN("=", null, null),
281
282    /**
283     * Property get operator as in: x.y.
284     * <br><strong>Syntax:</strong> <code>x.y</code>
285     * <br><strong>Method:</strong> <code>Object propertyGet(L x, R y);</code>.
286     */
287    PROPERTY_GET(".", "propertyGet", 2),
288
289    /**
290     * Property set operator as in: x.y = z.
291     * <br><strong>Syntax:</strong> <code>x.y = z</code>
292     * <br><strong>Method:</strong> <code>void propertySet(L x, R y, V z);</code>.
293     */
294    PROPERTY_SET(".=", "propertySet", 3),
295
296    /**
297     * Array get operator as in: x[y].
298     * <br><strong>Syntax:</strong> <code>x.y</code>
299     * <br><strong>Method:</strong> <code>Object arrayGet(L x, R y);</code>.
300     */
301    ARRAY_GET("[]", "arrayGet", 2),
302
303    /**
304     * Array set operator as in: x[y] = z.
305     * <br><strong>Syntax:</strong> <code>x[y] = z</code>
306     * <br><strong>Method:</strong> <code>void arraySet(L x, R y, V z);</code>.
307     */
308    ARRAY_SET("[]=", "arraySet", 3),
309
310    /**
311     * Iterator generator as in for(var x : y).
312     * If the returned Iterator is AutoCloseable, close will be called after the last execution of the loop block.
313     * <br><strong>Syntax:</strong> <code>for(var x : y){...} </code>
314     * <br><strong>Method:</strong> <code>Iterator&lt;Object&gt; forEach(R y);</code>.
315     * @since 3.1
316     */
317    FOR_EACH("for(...)", "forEach", 1);
318
319    /**
320     * The operator symbol.
321     */
322    private final String operator;
323
324    /**
325     * The associated operator method name.
326     */
327    private final String methodName;
328
329    /**
330     * The method arity (ie number of arguments).
331     */
332    private final int arity;
333
334    /**
335     * The base operator.
336     */
337    private final JexlOperator base;
338
339    /**
340     * Creates a base operator.
341     *
342     * @param o    the operator name
343     * @param m    the method name associated to this operator in a JexlArithmetic
344     * @param argc the number of parameters for the method
345     */
346    JexlOperator(final String o, final String m, final int argc) {
347        this.operator = o;
348        this.methodName = m;
349        this.arity = argc;
350        this.base = null;
351    }
352
353    /**
354     * Creates a side-effect operator.
355     *
356     * @param o the operator name
357     * @param m the method name associated to this operator in a JexlArithmetic
358     * @param b the base operator, ie + for +=
359     */
360    JexlOperator(final String o, final String m, final JexlOperator b) {
361        this.operator = o;
362        this.methodName = m;
363        this.arity = 2;
364        this.base = b;
365    }
366
367    /**
368     * Gets this operator symbol.
369     *
370     * @return the symbol
371     */
372    public final String getOperatorSymbol() {
373        return operator;
374    }
375
376    /**
377     * Gets this operator method name in a JexlArithmetic.
378     *
379     * @return the method name
380     */
381    public final String getMethodName() {
382        return methodName;
383    }
384
385    /**
386     * Gets this operator number of parameters.
387     *
388     * @return the method arity
389     */
390    public int getArity() {
391        return arity;
392    }
393
394    /**
395     * Gets the base operator.
396     *
397     * @return the base operator
398     */
399    public final JexlOperator getBaseOperator() {
400        return base;
401    }
402
403}