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 all 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 * For side effect operators, operators that modify the left-hand size value (+=, -=, etc), the user implemented 040 * overload methods may return: 041 * <ul> 042 * <li>JexlEngine.TRY_FAIL to let the default fallback behavior be executed.</li> 043 * <li>Any other value will be used as the new value to be assigned to the left-hand-side.</li> 044 * </ul> 045 * Note that side effect operators always return the left-hand side value (with an exception for postfix ++ and --). 046 * 047 * @since 3.0 048 */ 049public enum JexlOperator { 050 051 /** 052 * Add operator. 053 * <br><strong>Syntax:</strong> <code>x + y</code> 054 * <br><strong>Method:</strong> <code>T add(L x, R y);</code>. 055 * @see JexlArithmetic#add(Object, Object) 056 */ 057 ADD("+", "add", 2), 058 059 /** 060 * Subtract operator. 061 * <br><strong>Syntax:</strong> <code>x - y</code> 062 * <br><strong>Method:</strong> <code>T subtract(L x, R y);</code>. 063 * @see JexlArithmetic#subtract(Object, Object) 064 */ 065 SUBTRACT("-", "subtract", 2), 066 067 /** 068 * Multiply operator. 069 * <br><strong>Syntax:</strong> <code>x * y</code> 070 * <br><strong>Method:</strong> <code>T multiply(L x, R y);</code>. 071 * @see JexlArithmetic#multiply(Object, Object) 072 */ 073 MULTIPLY("*", "multiply", 2), 074 075 /** 076 * Divide operator. 077 * <br><strong>Syntax:</strong> <code>x / y</code> 078 * <br><strong>Method:</strong> <code>T divide(L x, R y);</code>. 079 * @see JexlArithmetic#divide(Object, Object) 080 */ 081 DIVIDE("/", "divide", 2), 082 083 /** 084 * Modulo operator. 085 * <br><strong>Syntax:</strong> <code>x % y</code> 086 * <br><strong>Method:</strong> <code>T mod(L x, R y);</code>. 087 * @see JexlArithmetic#mod(Object, Object) 088 */ 089 MOD("%", "mod", 2), 090 091 /** 092 * Bitwise-and operator. 093 * <br><strong>Syntax:</strong> <code>x & y</code> 094 * <br><strong>Method:</strong> <code>T and(L x, R y);</code>. 095 * @see JexlArithmetic#and(Object, Object) 096 */ 097 AND("&", "and", 2), 098 099 /** 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 >> 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 >>> 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 << 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 < 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 <= 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 > 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 >= 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 &= 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 >>= 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 >>> 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 << 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<Object> 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}