    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 *      https://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
    020import java.util.function.Consumer;
    021
    022/**
    023 * The JEXL operators.
    024 *
    025 * These are the operators that are executed by JexlArithmetic methods.
    026 *
    027 * <p>Each of them  associates a symbol to a method signature.
    028 * For instance, '+' is associated to 'T add(L x, R y)'.</p>
    029 *
    030 * <p>The default JexlArithmetic implements generic versions of these methods using Object as arguments.
    031 * You can use your own derived JexlArithmetic that override and/or overload those operator methods.
    032 * Note that these are overloads by convention, not actual Java overloads.
    033 * The following rules apply to all operator methods:</p>
    034 * <ul>
    035 * <li>Operator methods should be public</li>
    036 * <li>Operators return type should be respected when primitive (int, boolean,...)</li>
    037 * <li>Operators may be overloaded multiple times with different signatures</li>
    038 * <li>Operators may return JexlEngine.TRY_AGAIN to fallback on default JEXL implementation</li>
    039 * </ul>
    040 *
    041 * For side effect operators, operators that modify the left-hand size value (+=, -=, etc.), the user implemented
    042 * overload methods may return:
    043 * <ul>
    044 *     <li>JexlEngine.TRY_FAIL to let the default fallback behavior be executed.</li>
    045 *     <li>Any other value will be used as the new value to be assigned to the left-hand-side.</li>
    046 * </ul>
    047 * Note that side effect operators always return the left-hand side value (with an exception for postfix ++ and --).
    048 *
    049 * @since 3.0
    050 */
    051public enum JexlOperator {
    052
    053    /**
    054     * Add operator.
    055     * <br><strong>Syntax:</strong> {@code x + y}
    056     * <br><strong>Method:</strong> {@code T add(L x, R y);}.
    057     *
    058     * @see JexlArithmetic#add(Object, Object)
    059     */
    060    ADD("+", "add", 2),
    061
    062    /**
    063     * Subtract operator.
    064     * <br><strong>Syntax:</strong> {@code x - y}
    065     * <br><strong>Method:</strong> {@code T subtract(L x, R y);}.
    066     *
    067     * @see JexlArithmetic#subtract(Object, Object)
    068     */
    069    SUBTRACT("-", "subtract", 2),
    070
    071    /**
    072     * Multiply operator.
    073     * <br><strong>Syntax:</strong> {@code x * y}
    074     * <br><strong>Method:</strong> {@code T multiply(L x, R y);}.
    075     *
    076     * @see JexlArithmetic#multiply(Object, Object)
    077     */
    078    MULTIPLY("*", "multiply", 2),
    079
    080    /**
    081     * Divide operator.
    082     * <br><strong>Syntax:</strong> {@code x / y}
    083     * <br><strong>Method:</strong> {@code T divide(L x, R y);}.
    084     *
    085     * @see JexlArithmetic#divide(Object, Object)
    086     */
    087    DIVIDE("/", "divide", 2),
    088
    089    /**
    090     * Modulo operator.
    091     * <br><strong>Syntax:</strong> {@code x % y}
    092     * <br><strong>Method:</strong> {@code T mod(L x, R y);}.
    093     *
    094     * @see JexlArithmetic#mod(Object, Object)
    095     */
    096    MOD("%", "mod", 2),
    097
    098    /**
    099     * Bitwise-and operator.
    100     * <br><strong>Syntax:</strong> {@code x & y}
    101     * <br><strong>Method:</strong> {@code T and(L x, R y);}.
    102     *
    103     * @see JexlArithmetic#and(Object, Object)
    104     */
    105    AND("&", "and", 2),
    106
    107    /**
    108     * Bitwise-or operator.
    109     * <br><strong>Syntax:</strong> {@code x | y}
    110     * <br><strong>Method:</strong> {@code T or(L x, R y);}.
    111     *
    112     * @see JexlArithmetic#or(Object, Object)
    113     */
    114    OR("|", "or", 2),
    115
    116    /**
    117     * Bitwise-xor operator.
    118     * <br><strong>Syntax:</strong> {@code x ^ y}
    119     * <br><strong>Method:</strong> {@code T xor(L x, R y);}.
    120     *
    121     * @see JexlArithmetic#xor(Object, Object)
    122     */
    123    XOR("^", "xor", 2),
    124
    125    /**
    126     * Bit-pattern right-shift operator.
    127     * <br><strong>Syntax:</strong> {@code x >> y}
    128     * <br><strong>Method:</strong> {@code T rightShift(L x, R y);}.
    129     *
    130     * @see JexlArithmetic#shiftRight(Object, Object)
    131     */
    132    SHIFTRIGHT(">>", "shiftRight", 2),
    133
    134    /**
    135     * Bit-pattern right-shift unsigned operator.
    136     * <br><strong>Syntax:</strong> {@code x >>> y}
    137     * <br><strong>Method:</strong> {@code T rightShiftUnsigned(L x, R y);}.
    138     *
    139     * @see JexlArithmetic#shiftRightUnsigned(Object, Object)
    140     */
    141    SHIFTRIGHTU(">>>", "shiftRightUnsigned", 2),
    142
    143    /**
    144     * Bit-pattern left-shift operator.
    145     * <br><strong>Syntax:</strong> {@code x << y}
    146     * <br><strong>Method:</strong> {@code T leftShift(L x, R y);}.
    147     *
    148     * @see JexlArithmetic#shiftLeft(Object, Object)
    149     */
    150    SHIFTLEFT("<<", "shiftLeft", 2),
    151
    152    /**
    153     * Equals operator.
    154     * <br><strong>Syntax:</strong> {@code x == y}
    155     * <br><strong>Method:</strong> {@code boolean equals(L x, R y);}.
    156     *
    157     * @see JexlArithmetic#equals(Object, Object)
    158     */
    159    EQ("==", "equals", 2),
    160
    161    /**
    162     * Equal-strict operator.
    163     * <br><strong>Syntax:</strong> {@code x === y}
    164     * <br><strong>Method:</strong> {@code boolean strictEquals(L x, R y);}.
    165     *
    166     * @see JexlArithmetic#strictEquals(Object, Object)
    167     */
    168    EQSTRICT("===", "strictEquals", 2),
    169
    170    /**
    171     * Less-than operator.
    172     * <br><strong>Syntax:</strong> {@code x < y}
    173     * <br><strong>Method:</strong> {@code boolean lessThan(L x, R y);}.
    174     *
    175     * @see JexlArithmetic#lessThan(Object, Object)
    176     */
    177    LT("<", "lessThan", 2),
    178
    179    /**
    180     * Less-than-or-equal operator.
    181     * <br><strong>Syntax:</strong> {@code x <= y}
    182     * <br><strong>Method:</strong> {@code boolean lessThanOrEqual(L x, R y);}.
    183     *
    184     * @see JexlArithmetic#lessThanOrEqual(Object, Object)
    185     */
    186    LTE("<=", "lessThanOrEqual", 2),
    187
    188    /**
    189     * Greater-than operator.
    190     * <br><strong>Syntax:</strong> {@code x > y}
    191     * <br><strong>Method:</strong> {@code boolean greaterThan(L x, R y);}.
    192     *
    193     * @see JexlArithmetic#greaterThan(Object, Object)
    194     */
    195    GT(">", "greaterThan", 2),
    196
    197    /**
    198     * Greater-than-or-equal operator.
    199     * <br><strong>Syntax:</strong> {@code x >= y}
    200     * <br><strong>Method:</strong> {@code boolean greaterThanOrEqual(L x, R y);}.
    201     *
    202     * @see JexlArithmetic#greaterThanOrEqual(Object, Object)
    203     */
    204    GTE(">=", "greaterThanOrEqual", 2),
    205
    206    /**
    207     * Contains operator.
    208     * <br><strong>Syntax:</strong> {@code x =~ y}
    209     * <br><strong>Method:</strong> {@code boolean contains(L x, R y);}.
    210     *
    211     * @see JexlArithmetic#contains(Object, Object)
    212     */
    213    CONTAINS("=~", "contains", 2),
    214
    215    /**
    216     * Starts-with operator.
    217     * <br><strong>Syntax:</strong> {@code x =^ y}
    218     * <br><strong>Method:</strong> {@code boolean startsWith(L x, R y);}.
    219     *
    220     * @see JexlArithmetic#startsWith(Object, Object)
    221     */
    222    STARTSWITH("=^", "startsWith", 2),
    223
    224    /**
    225     * Ends-with operator.
    226     * <br><strong>Syntax:</strong> {@code x =$ y}
    227     * <br><strong>Method:</strong> {@code boolean endsWith(L x, R y);}.
    228     *
    229     * @see JexlArithmetic#endsWith(Object, Object)
    230     */
    231    ENDSWITH("=$", "endsWith", 2),
    232
    233    /**
    234     * Not operator.
    235     * <br><strong>Syntax:</strong> {@code !x}
    236     * <br><strong>Method:</strong> {@code T not(L x);}.
    237     *
    238     * @see JexlArithmetic#not(Object)
    239     */
    240    NOT("!", "not", 1),
    241
    242    /**
    243     * Complement operator.
    244     * <br><strong>Syntax:</strong> {@code ~x}
    245     * <br><strong>Method:</strong> {@code T complement(L x);}.
    246     *
    247     * @see JexlArithmetic#complement(Object)
    248     */
    249    COMPLEMENT("~", "complement", 1),
    250
    251    /**
    252     * Negate operator.
    253     * <br><strong>Syntax:</strong> {@code -x}
    254     * <br><strong>Method:</strong> {@code T negate(L x);}.
    255     *
    256     * @see JexlArithmetic#negate(Object)
    257     */
    258    NEGATE("-", "negate", 1),
    259
    260    /**
    261     * Positivize operator.
    262     * <br><strong>Syntax:</strong> {@code +x}
    263     * <br><strong>Method:</strong> {@code T positivize(L x);}.
    264     *
    265     * @see JexlArithmetic#positivize(Object)
    266     */
    267    POSITIVIZE("+", "positivize", 1),
    268
    269    /**
    270     * Empty operator.
    271     * <br><strong>Syntax:</strong> {@code empty x} or {@code empty(x)}
    272     * <br><strong>Method:</strong> {@code boolean empty(L x);}.
    273     *
    274     * @see JexlArithmetic#empty(Object)
    275     */
    276    EMPTY("empty", "empty", 1),
    277
    278    /**
    279     * Size operator.
    280     * <br><strong>Syntax:</strong> {@code size x} or {@code size(x)}
    281     * <br><strong>Method:</strong> {@code int size(L x);}.
    282     *
    283     * @see JexlArithmetic#size(Object)
    284     */
    285    SIZE("size", "size", 1),
    286
    287    /**
    288     * Self-add operator.
    289     * <br><strong>Syntax:</strong> {@code x += y}
    290     * <br><strong>Method:</strong> {@code T selfAdd(L x, R y);}.
    291     */
    292    SELF_ADD("+=", "selfAdd", ADD),
    293
    294    /**
    295     * Self-subtract operator.
    296     * <br><strong>Syntax:</strong> {@code x -= y}
    297     * <br><strong>Method:</strong> {@code T selfSubtract(L x, R y);}.
    298     */
    299    SELF_SUBTRACT("-=", "selfSubtract", SUBTRACT),
    300
    301    /**
    302     * Self-multiply operator.
    303     * <br><strong>Syntax:</strong> {@code x *= y}
    304     * <br><strong>Method:</strong> {@code T selfMultiply(L x, R y);}.
    305     */
    306    SELF_MULTIPLY("*=", "selfMultiply", MULTIPLY),
    307
    308    /**
    309     * Self-divide operator.
    310     * <br><strong>Syntax:</strong> {@code x /= y}
    311     * <br><strong>Method:</strong> {@code T selfDivide(L x, R y);}.
    312     */
    313    SELF_DIVIDE("/=", "selfDivide", DIVIDE),
    314
    315    /**
    316     * Self-modulo operator.
    317     * <br><strong>Syntax:</strong> {@code x %= y}
    318     * <br><strong>Method:</strong> {@code T selfMod(L x, R y);}.
    319     */
    320    SELF_MOD("%=", "selfMod", MOD),
    321
    322    /**
    323     * Self-and operator.
    324     * <br><strong>Syntax:</strong> {@code x &amp;= y}
    325     * <br><strong>Method:</strong> {@code T selfAnd(L x, R y);}.
    326     */
    327    SELF_AND("&=", "selfAnd", AND),
    328
    329    /**
    330     * Self-or operator.
    331     * <br><strong>Syntax:</strong> {@code x |= y}
    332     * <br><strong>Method:</strong> {@code T selfOr(L x, R y);}.
    333     */
    334    SELF_OR("|=", "selfOr", OR),
    335
    336    /**
    337     * Self-xor operator.
    338     * <br><strong>Syntax:</strong> {@code x ^= y}
    339     * <br><strong>Method:</strong> {@code T selfXor(L x, R y);}.
    340     */
    341    SELF_XOR("^=", "selfXor", XOR),
    342
    343    /**
    344     * Self-right-shift operator.
    345     * <br><strong>Syntax:</strong> {@code x >>= y}
    346     * <br><strong>Method:</strong> {@code T selfShiftRight(L x, R y);}.
    347     */
    348    SELF_SHIFTRIGHT(">>=", "selfShiftRight", SHIFTRIGHT),
    349
    350    /**
    351     * Self-right-shift unsigned operator.
    352     * <br><strong>Syntax:</strong> {@code x >>> y}
    353     * <br><strong>Method:</strong> {@code T selfShiftRightUnsigned(L x, R y);}.
    354     */
    355    SELF_SHIFTRIGHTU(">>>=", "selfShiftRightUnsigned", SHIFTRIGHTU),
    356
    357    /**
    358     * Self-left-shift operator.
    359     * <br><strong>Syntax:</strong> {@code x << y}
    360     * <br><strong>Method:</strong> {@code T selfShiftLeft(L x, R y);}.
    361     */
    362    SELF_SHIFTLEFT("<<=", "selfShiftLeft", SHIFTLEFT),
    363
    364    /**
    365     * Increment pseudo-operator.
    366     * <br>No syntax, used as helper for the prefix and postfix versions of {@code ++}.
    367     *
    368     * @see JexlArithmetic#increment(Object)
    369     */
    370    INCREMENT("+1", "increment", 1),
    371
    372    /**
    373     * Decrement pseudo-operator.
    374     * <br>No syntax, used as helper for the prefix and postfix versions of {@code --}.
    375     *
    376     * @see JexlArithmetic#decrement(Object)
    377     */
    378    DECREMENT("-1", "decrement", 1),
    379
    380    /**
    381     * Prefix ++ operator, increments and returns the value after incrementing.
    382     * <br><strong>Syntax:</strong> {@code ++x}
    383     * <br><strong>Method:</strong> {@code T incrementAndGet(L x);}.
    384     */
    385    INCREMENT_AND_GET("++.", "incrementAndGet", INCREMENT, 1),
    386
    387    /**
    388     * Postfix ++, increments and returns the value before incrementing.
    389     * <br><strong>Syntax:</strong> {@code x++}
    390     * <br><strong>Method:</strong> {@code T getAndIncrement(L x);}.
    391     */
    392    GET_AND_INCREMENT(".++", "getAndIncrement", INCREMENT, 1),
    393
    394    /**
    395     * Prefix --, decrements and returns the value after decrementing.
    396     * <br><strong>Syntax:</strong> {@code --x}
    397     * <br><strong>Method:</strong> {@code T decrementAndGet(L x);}.
    398     */
    399    DECREMENT_AND_GET("--.", "decrementAndGet", DECREMENT, 1),
    400
    401    /**
    402     * Postfix --, decrements and returns the value before decrementing.
    403     * <br><strong>Syntax:</strong> {@code x--}
    404     * <br><strong>Method:</strong> {@code T getAndDecrement(L x);}.
    405     */
    406    GET_AND_DECREMENT(".--", "getAndDecrement", DECREMENT, 1),
    407
    408    /**
    409     * Marker for side effect.
    410     * <p>
    411     * Returns this from 'self*' overload method to let the engine know the side effect has been performed and
    412     * there is no need to assign the result.
    413     * </p>
    414     *
    415     * @deprecated 3.5.0
    416     */
    417    @Deprecated
    418    ASSIGN("=", null, null),
    419
    420    /**
    421     * Property get operator as in: x.y.
    422     * <br><strong>Syntax:</strong> {@code x.y}
    423     * <br><strong>Method:</strong> {@code Object propertyGet(L x, R y);}.
    424     */
    425    PROPERTY_GET(".", "propertyGet", 2),
    426
    427    /**
    428     * Property set operator as in: x.y = z.
    429     * <br><strong>Syntax:</strong> {@code x.y = z}
    430     * <br><strong>Method:</strong> {@code void propertySet(L x, R y, V z);}.
    431     */
    432    PROPERTY_SET(".=", "propertySet", 3),
    433
    434    /**
    435     * Array get operator as in: x[y].
    436     * <br><strong>Syntax:</strong> {@code x.y}
    437     * <br><strong>Method:</strong> {@code Object arrayGet(L x, R y);}.
    438     */
    439    ARRAY_GET("[]", "arrayGet", 2),
    440
    441    /**
    442     * Array set operator as in: x[y] = z.
    443     * <br><strong>Syntax:</strong> {@code x[y] = z}
    444     * <br><strong>Method:</strong> {@code void arraySet(L x, R y, V z);}.
    445     */
    446    ARRAY_SET("[]=", "arraySet", 3),
    447
    448    /**
    449     * Iterator generator as in for(var x : y).
    450     * If the returned Iterator is AutoCloseable, close will be called after the last execution of the loop block.
    451     * <br><strong>Syntax:</strong> <code>for(var x : y){...}</code>
    452     * <br><strong>Method:</strong> {@code Iterator<Object> forEach(R y);}.
    453     *
    454     * @since 3.1
    455     */
    456    FOR_EACH("for(...)", "forEach", 1),
    457
    458    /**
    459     * Test condition in if, for, while.
    460     * <br><strong>Method:</strong> {@code boolean testCondition(R y);}.
    461     *
    462     * @since 3.3
    463     */
    464    CONDITION("?", "testCondition", 1),
    465
    466    /**
    467     * Compare overload as in compare(x, y).
    468     * <br><strong>Method:</strong> {@code boolean compare(L x, R y);}.
    469     *
    470     * @since 3.5.0
    471     */
    472    COMPARE("<>", "compare", 2),
    473
    474    /**
    475     * Not-Contains operator.
    476     * <p>Not overridable, calls !(contain(...))</p>
    477     */
    478    NOT_CONTAINS("!~", null, CONTAINS),
    479
    480    /**
    481     * Not-Starts-With operator.
    482     * <p>Not overridable, calls !(startsWith(...))</p>
    483     */
    484    NOT_STARTSWITH("!^", null, STARTSWITH),
    485
    486    /**
    487     * Not-Ends-With operator.
    488     * <p>Not overridable, calls !(endsWith(...))</p>
    489     */
    490    NOT_ENDSWITH("!$", null, ENDSWITH),;
    491
    492    /**
    493     * The operator symbol.
    494     */
    495    private final String operator;
    496
    497    /**
    498     * The associated operator method name.
    499     */
    500    private final String methodName;
    501
    502    /**
    503     * The method arity (ie number of arguments).
    504     */
    505    private final int arity;
    506
    507    /**
    508     * The base operator.
    509     */
    510    private final JexlOperator base;
    511
    512    /**
    513     * Creates a base operator.
    514     *
    515     * @param o    the operator name
    516     * @param m    the method name associated to this operator in a JexlArithmetic
    517     * @param argc the number of parameters for the method
    518     */
    519    JexlOperator(final String o, final String m, final int argc) {
    520        this(o, m, null, argc);
    521    }
    522
    523    /**
    524     * Creates a side effect operator with arity == 2.
    525     *
    526     * @param o the operator name
    527     * @param m the method name associated to this operator in a JexlArithmetic
    528     * @param b the base operator, ie + for +=
    529     */
    530    JexlOperator(final String o, final String m, final JexlOperator b) {
    531        this(o, m, b, 2);
    532    }
    533
    534    /**
    535     * Creates a side effect operator.
    536     *
    537     * @param o the operator name
    538     * @param m the method name associated to this operator in a JexlArithmetic
    539     * @param b the base operator, ie + for +=
    540     * @param a the operator arity
    541     */
    542    JexlOperator(final String o, final String m, final JexlOperator b, final int a) {
    543        this.operator = o;
    544        this.methodName = m;
    545        this.arity = a;
    546        this.base = b;
    547    }
    548
    549    /**
    550     * Gets this operator number of parameters.
    551     *
    552     * @return the method arity
    553     */
    554    public int getArity() {
    555        return arity;
    556    }
    557
    558    /**
    559     * Gets the base operator.
    560     *
    561     * @return the base operator
    562     */
    563    public final JexlOperator getBaseOperator() {
    564        return base;
    565    }
    566
    567    /**
    568     * Gets this operator method name in a JexlArithmetic.
    569     *
    570     * @return the method name
    571     */
    572    public final String getMethodName() {
    573        return methodName;
    574    }
    575
    576    /**
    577     * Gets this operator symbol.
    578     *
    579     * @return the symbol
    580     */
    581    public final String getOperatorSymbol() {
    582        return operator;
    583    }
    584
    585    /**
    586     * Uberspect that solves and evaluates JexlOperator overloads.
    587     * <p>This is used by the interpreter to find and execute operator overloads implemented in a derived
    588     * JexlArithmetic - or in some cases, as methods of the left argument type (contains, size, ...).</p>
    589     * <p>This also allows reusing the core logic when extending the applicative type-system; for
    590     * instance, implementing a Comparator class that calls compare
    591     * (<code>operator.tryOverload(this, JexlOperator.COMPARE, left, right)</code>, etc.</p>
    592     *
    593     * @since 3.5.0
    594     */
    595    public interface Uberspect extends JexlArithmetic.Uberspect {
    596
    597        /**
    598         * Try to find the most specific method and evaluate an operator.
    599         * <p>This method does not call {@link #overloads(JexlOperator)} and shall not be called with an
    600         * assignment operator; use {@link #tryAssignOverload(JexlCache.Reference, JexlOperator, Consumer, Object...)}
    601         * in that case.</p>
    602         *
    603         * @param reference an optional reference caching resolved method or failing signature
    604         * @param operator the operator
    605         * @param args      the arguments
    606         * @return TRY_FAILED if no specific method could be found, the evaluation result otherwise
    607         */
    608        Object tryOverload(JexlCache.Reference reference, JexlOperator operator, Object...args);
    609
    610        /**
    611         * Evaluates an assign operator.
    612         * <p>
    613         * This takes care of finding and caching the operator method when appropriate.
    614         * If an overloads returns a value not-equal to TRY_FAILED, it means the side-effect is complete.
    615         * Otherwise, {@code a += b <=> a = a + b}
    616         * </p>
    617         *
    618         * @param node     an optional reference caching resolved method or failing signature
    619         * @param operator the operator
    620         * @param assign   the actual function that performs the side effect
    621         * @param args     the arguments, the first one being the target of assignment
    622         * @return JexlEngine.TRY_FAILED if no operation was performed,
    623         *         the value to use as the side effect argument otherwise
    624         */
    625        Object tryAssignOverload(final JexlCache.Reference node,
    626                                 final JexlOperator operator,
    627                                 final Consumer<Object> assign,
    628                                 final Object... args);
    629
    630        /**
    631         * Calculate the {@code size} of various types:
    632         * Collection, Array, Map, String, and anything that has an int size() method.
    633         * <p>Seeks an overload or use the default arithmetic implementation.</p>
    634         * <p>Note that the result may not be an integer.
    635         *
    636         * @param node   an optional reference caching resolved method or failing signature
    637         * @param object the object to get the size of
    638         * @return the evaluation result
    639         */
    640        Object size(final JexlCache.Reference node, final Object object);
    641
    642        /**
    643         * Check for emptiness of various types: Collection, Array, Map, String, and anything that has a boolean isEmpty()
    644         * method.
    645         * <p>Seeks an overload or use the default arithmetic implementation.</p>
    646         * <p>Note that the result may not be a boolean.
    647         *
    648         * @param node   the node holding the object
    649         * @param object the object to check the emptiness of
    650         * @return the evaluation result
    651         */
    652        Object empty(final JexlCache.Reference node, final Object object);
    653
    654        /**
    655         * The 'match'/'in' operator implementation.
    656         * <p>Seeks an overload or use the default arithmetic implementation.</p>
    657         * <p>
    658         * Note that 'x in y' or 'x matches y' means 'y contains x' ;
    659         * the JEXL operator arguments order syntax is the reverse of this method call.
    660         * </p>
    661         *
    662         * @param node  an optional reference caching resolved method or failing signature
    663         * @param operator    the calling operator, =~ or !~
    664         * @param right the left operand
    665         * @param left  the right operand
    666         * @return true if left matches right, false otherwise
    667         */
    668        boolean contains(final JexlCache.Reference node,
    669                         final JexlOperator operator,
    670                         final Object left,
    671                         final Object right);
    672
    673        /**
    674         * The 'startsWith' operator implementation.
    675         * <p>Seeks an overload or use the default arithmetic implementation.</p>
    676         *
    677         * @param node     an optional reference caching resolved method or failing signature
    678         * @param operator the calling operator, $= or $!
    679         * @param left     the left operand
    680         * @param right    the right operand
    681         * @return true if left starts with right, false otherwise
    682         */
    683        boolean startsWith(final JexlCache.Reference node,
    684                           final JexlOperator operator,
    685                           final Object left,
    686                           final Object right);
    687
    688        /**
    689         * The 'endsWith' operator implementation.
    690         * <p>Seeks an overload or use the default arithmetic implementation.</p>
    691         *
    692         * @param node     an optional reference caching resolved method or failing signature
    693         * @param operator the calling operator, ^= or ^!
    694         * @param left     the left operand
    695         * @param right    the right operand
    696         * @return true if left ends with right, false otherwise
    697         */
    698        boolean endsWith(final JexlCache.Reference node,
    699                         final JexlOperator operator,
    700                         final Object left,
    701                         final Object right);
    702    }
    703}