    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}