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 & 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 >> 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 * 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 < 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 <= 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 > 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 >= 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 &= 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 >>= 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 >>> 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 << 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<Object> 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 }