001package com.thetransactioncompany.jsonrpc2.util; 002 003 004import java.util.List; 005import java.util.Map; 006 007import com.thetransactioncompany.jsonrpc2.JSONRPC2Error; 008 009 010/** 011 * Utility class for retrieving JSON-RPC 2.0 positional parameters (packed into 012 * a JSON Array). 013 * 014 * <p>Provides a set of getter methods according to the expected parameter type 015 * (number, string, etc.) and whether the parameter is mandatory or optional: 016 * 017 * <ul> 018 * <li>{@code getXXX(param_pos)} for mandatory parameters, where 019 * {@code XXX} is the expected parameter type. 020 * <li>{@code getOptXXX(param_pos, default_value)} for optional parameters, 021 * specifying a default value. 022 * </ul> 023 * 024 * <p>There are also generic getter methods that let you do the type conversion 025 * yourself. 026 * 027 * <p>If a parameter cannot be retrieved, e.g. due to a missing mandatory 028 * parameter or bad type, a 029 * {@link com.thetransactioncompany.jsonrpc2.JSONRPC2Error#INVALID_PARAMS} 030 * exception is thrown. 031 * 032 * <p>Example: suppose you have a method with 3 positional parameters where the 033 * first two are mandatory and the last is optional and has a default value of 034 * {@code true}. 035 * 036 * <pre> 037 * // Parse received request string 038 * JSONRPC2Request request = null; 039 * 040 * try { 041 * request = JSONRPC2Request.parse(jsonString); 042 * } catch (JSONRPC2ParseException e) { 043 * // handle exception... 044 * } 045 * 046 * // Create a new retriever for positional parameters 047 * List params = (List)request.getParams(); 048 * PositionalParamsRetriever r = new PositionalParamsRetriever(params); 049 * 050 * try { 051 * // Extract first mandatory string parameter 052 * String param1 = r.getString(0); 053 * 054 * // Extract second integer parameter 055 * int param2 = r.getInt(1); 056 * 057 * // Extract third optional boolean parameter which defaults to true 058 * boolean param3 = r.getOptBoolean(2, true); 059 * 060 * } catch (JSONRPC2Error e) { 061 * // A JSONRPC2Error.INVALID_PARAMS will be thrown to indicate 062 * // an unexpected parameter type or a missing mandatory parameter. 063 * // You can use it straight away to create the appropriate 064 * // JSON-RPC 2.0 error response. 065 * JSONRPC2Response response = new JSONRPC2Response(e, null); 066 * } 067 * </pre> 068 * 069 * @author Vladimir Dzhuvinov 070 */ 071public class PositionalParamsRetriever 072 extends ParamsRetriever { 073 074 075 /** 076 * The positional parameters interface. 077 */ 078 private List<Object> params = null; 079 080 081 /** 082 * Throws a JSON-RPC 2.0 error indicating a missing positional 083 * parameter. 084 * 085 * @param position The parameter position. Should be non-negative. 086 * 087 * @throws JSONRPC2Error Formatted JSON-RPC 2.0 error. 088 */ 089 private static void throwMissingParameterException(final int position) 090 throws JSONRPC2Error { 091 092 throw JSONRPC2Error.INVALID_PARAMS. 093 appendMessage(": Missing parameter at position " + position); 094 } 095 096 097 /** 098 * Throws a JSON-RPC 2.0 error indicating a positional parameter with 099 * unexpected {@code null} value. 100 * 101 * @param position The parameter position. Should be non-negative. 102 * 103 * @throws JSONRPC2Error Formatted JSON-RPC 2.0 error. 104 */ 105 private static void throwNullParameterException(final int position) 106 throws JSONRPC2Error { 107 108 throw JSONRPC2Error.INVALID_PARAMS. 109 appendMessage(": Parameter at position " + position + " must not be null"); 110 } 111 112 113 /** 114 * Throws a JSON-RPC 2.0 error indicating a positional parameter with 115 * an unexpected enumerated value. 116 * 117 * @param position The parameter position. Should be non-negative. 118 * @param enumStrings The acceptable string values. Must not be 119 * {@code null}. 120 * 121 * @throws JSONRPC2Error Formatted JSON-RPC 2.0 error. 122 */ 123 private static void throwEnumParameterException(final int position, 124 final String[] enumStrings) 125 throws JSONRPC2Error { 126 127 StringBuilder msg = new StringBuilder(": Enumerated parameter at position " + 128 position + "\" must have values "); 129 130 for (int i=0; i < enumStrings.length; i++) { 131 132 if (i > 0 && i == enumStrings.length - 1) 133 msg.append(" or "); 134 135 else if (i > 0) 136 msg.append(", "); 137 138 msg.append('"'); 139 msg.append(enumStrings[i]); 140 msg.append('"'); 141 } 142 143 throw JSONRPC2Error.INVALID_PARAMS.appendMessage(msg.toString()); 144 } 145 146 147 /** 148 * Throws a JSON-RPC 2.0 error indicating a positional parameter with 149 * an unexpected enumerated value. 150 * 151 * @param position The parameter position. Should be non-negative. 152 * @param enumClass The enumeration class specifying the acceptable 153 * string values. Must not be {@code null}. 154 * 155 * @throws JSONRPC2Error Formatted JSON-RPC 2.0 error. 156 */ 157 private static <T extends Enum<T>> void throwEnumParameterException(final int position, 158 final Class<T> enumClass) 159 throws JSONRPC2Error { 160 161 StringBuilder msg = new StringBuilder(": Enumerated parameter at position " + 162 position + " must have values "); 163 164 T[] constants = enumClass.getEnumConstants(); 165 166 for (int i = 0; i < constants.length; i++) { 167 168 if (i > 0 && i == constants.length - 1) 169 msg.append(" or "); 170 171 else if (i > 0) 172 msg.append(", "); 173 174 msg.append('"'); 175 msg.append(constants[i].toString()); 176 msg.append('"'); 177 } 178 179 throw JSONRPC2Error.INVALID_PARAMS.appendMessage(msg.toString()); 180 } 181 182 183 /** 184 * Creates a JSON-RPC 2.0 error indicating a positional parameter with 185 * an unexpected JSON type. 186 * 187 * @param position The parameter position. Should be non-negative. 188 * 189 * @return Formatted JSON-RPC 2.0 error. 190 */ 191 private static JSONRPC2Error newUnexpectedParameterTypeException(final int position) { 192 193 return JSONRPC2Error.INVALID_PARAMS. 194 appendMessage(": Parameter at position " + position + " has an unexpected JSON type"); 195 } 196 197 198 /** 199 * Creates a JSON-RPC 2.0 error indicating an array exception. 200 * 201 * @param position The parameter position. Should be non-negative. 202 * 203 * @return Formatted JSON-RPC 2.0 error. 204 */ 205 private static JSONRPC2Error newArrayException(final int position) { 206 207 return JSONRPC2Error.INVALID_PARAMS. 208 appendMessage(": Parameter at position " + position + " caused an array exception"); 209 } 210 211 212 /** 213 * Creates a new positional parameters retriever from the specified 214 * value list. 215 * 216 * @param params The positional parameters list. Must not be 217 * {@code null}. 218 */ 219 public PositionalParamsRetriever(final List<Object> params) { 220 221 if (params == null) 222 throw new IllegalArgumentException("The parameters list must not be null"); 223 224 this.params = params; 225 } 226 227 228 /** 229 * Gets the positional parameters for this retriever. 230 * 231 * @return The positional parameters. 232 */ 233 public List<Object> getParams() { 234 235 return params; 236 } 237 238 239 @Override 240 public int size() { 241 242 return params.size(); 243 } 244 245 246 /** 247 * Returns {@code true} a parameter at the specified position exists, 248 * else {@code false}. 249 * 250 * @param position The parameter position. 251 * 252 * @return {@code true} if the parameter exists, else {@code false}. 253 */ 254 public boolean hasParam(final int position) { 255 256 return position < params.size(); 257 } 258 259 260 /** 261 * @see #hasParam 262 */ 263 @Deprecated 264 public boolean hasParameter(final int position) { 265 266 return hasParam(position); 267 } 268 269 270 /** 271 * Throws a {@code JSONRPC2Error.INVALID_PARAMS} exception if there is 272 * no parameter at the specified position. 273 * 274 * <p>You may use this method to fire the proper JSON-RPC 2.0 error 275 * on a missing mandatory parameter. 276 * 277 * @param position The parameter position, starting with zero for the 278 * first. 279 * 280 * @throws JSONRPC2Error On a missing parameter 281 * ({@link JSONRPC2Error#INVALID_PARAMS}). 282 */ 283 public void ensureParam(final int position) 284 throws JSONRPC2Error { 285 286 if (position >= params.size() ) 287 throwMissingParameterException(position); 288 } 289 290 291 /** 292 * @see #ensureParam 293 */ 294 @Deprecated 295 public void ensureParameter(final int position) 296 throws JSONRPC2Error { 297 298 ensureParam(position); 299 } 300 301 302 /** 303 * Throws a {@code JSONRPC2Error.INVALID_PARAMS} exception if there is 304 * no parameter at the specified position, its value is {@code null}, 305 * or its type doesn't map to the specified. 306 * 307 * <p>You may use this method to fire the proper JSON-RPC 2.0 error 308 * on a missing or badly-typed mandatory parameter. 309 * 310 * @param position The parameter position. 311 * @param clazz The corresponding Java class that the parameter 312 * should map to (any one of the return types of the 313 * {@code getXXX()} getter methods. Set to 314 * {@code Object.class} to allow any type. Must not be 315 * {@code null}. 316 * 317 * @throws JSONRPC2Error On a missing parameter, {@code null} value or 318 * bad type ({@link JSONRPC2Error#INVALID_PARAMS}). 319 */ 320 public <T> void ensureParam(final int position, final Class<T> clazz) 321 throws JSONRPC2Error { 322 323 ensureParameter(position, clazz, false); 324 } 325 326 327 /** 328 * @see #ensureParam(int, Class) 329 */ 330 @Deprecated 331 public <T> void ensureParameter(final int position, final Class<T> clazz) 332 throws JSONRPC2Error { 333 334 ensureParam(position, clazz); 335 } 336 337 338 /** 339 * Throws a {@code JSONRPC2Error.INVALID_PARAMS} exception if there is 340 * no parameter at the specified position or its type doesn't map to 341 * the specified. 342 * 343 * <p>You may use this method to fire the proper JSON-RPC 2.0 error 344 * on a missing or badly-typed mandatory parameter. 345 * 346 * @param position The parameter position. 347 * @param clazz The corresponding Java class that the parameter 348 * should map to (any one of the return types of the 349 * {@code getXXX()} getter methods. Set to 350 * {@code Object.class} to allow any type. Must not be 351 * {@code null}. 352 * @param allowNull If {@code true} allows a {@code null} parameter 353 * value. 354 * 355 * @throws JSONRPC2Error On a missing parameter or bad type 356 * ({@link JSONRPC2Error#INVALID_PARAMS}). 357 */ 358 public <T> void ensureParam(final int position, 359 final Class<T> clazz, 360 final boolean allowNull) 361 throws JSONRPC2Error { 362 363 // First, check existence only 364 ensureParameter(position); 365 366 // Now check type 367 Object value = params.get(position); 368 369 if (value == null) { 370 371 if (allowNull) 372 return; // ok 373 else 374 throwNullParameterException(position); 375 } 376 377 if (! clazz.isAssignableFrom(value.getClass())) 378 throw newUnexpectedParameterTypeException(position); 379 } 380 381 382 /** 383 * @see #ensureParam(int, Class, boolean) 384 */ 385 @Deprecated 386 public <T> void ensureParameter(final int position, 387 final Class<T> clazz, 388 final boolean allowNull) 389 throws JSONRPC2Error { 390 391 ensureParam(position, clazz, allowNull); 392 } 393 394 395 /** 396 * Retrieves the specified parameter which can be of any type. Use this 397 * generic getter if you want to cast the value yourself. Otherwise 398 * look at the typed {@code get*} methods. 399 * 400 * @param position The parameter position. 401 * 402 * @return The parameter value. 403 * 404 * @throws JSONRPC2Error On a missing parameter 405 * ({@link JSONRPC2Error#INVALID_PARAMS}). 406 */ 407 public Object get(final int position) 408 throws JSONRPC2Error { 409 410 ensureParameter(position); 411 412 return params.get(position); 413 } 414 415 416 /** 417 * Retrieves the specified parameter which must map to the provided 418 * class (use the appropriate wrapper class for primitive types). 419 * 420 * @param position The parameter position. 421 * @param clazz The corresponding Java class that the parameter 422 * should map to (any one of the return types of the 423 * {@code getXXX()} getter methods. Set to 424 * {@code Object.class} to allow any type. Must not be 425 * {@code null}. 426 * 427 * @return The parameter value. 428 * 429 * @throws JSONRPC2Error On a missing parameter, {@code null} value or 430 * bad type ({@link JSONRPC2Error#INVALID_PARAMS}). 431 */ 432 public <T> T get(final int position, final Class<T> clazz) 433 throws JSONRPC2Error { 434 435 return get(position, clazz, false); 436 } 437 438 439 /** 440 * Retrieves the specified parameter which must map to the provided 441 * class (use the appropriate wrapper class for primitive types). 442 * 443 * @param position The parameter position. 444 * @param clazz The corresponding Java class that the parameter 445 * should map to (any one of the return types of the 446 * {@code getXXX()} getter methods. Set to 447 * {@code Object.class} to allow any type. Must not be 448 * {@code null}. 449 * @param allowNull If {@code true} allows a {@code null} parameter 450 * value. 451 * 452 * @return The parameter value. 453 * 454 * @throws JSONRPC2Error On a missing parameter or bad type 455 * ({@link JSONRPC2Error#INVALID_PARAMS}). 456 */ 457 @SuppressWarnings("unchecked") 458 public <T> T get(final int position, final Class<T> clazz, final boolean allowNull) 459 throws JSONRPC2Error { 460 461 ensureParameter(position, clazz, allowNull); 462 463 try { 464 return (T)params.get(position); 465 466 } catch (ClassCastException e) { 467 468 throw newUnexpectedParameterTypeException(position); 469 } 470 } 471 472 473 /** 474 * Retrieves the specified optional parameter which must map to the 475 * provided class (use the appropriate wrapper class for primitive 476 * types). If the parameter doesn't exist the method returns the 477 * specified default value. 478 * 479 * @param position The parameter position. 480 * @param clazz The corresponding Java class that the parameter 481 * should map to (any one of the return types of 482 * the {@code getXXX()} getter methods. Set to 483 * {@code Object.class} to allow any type. Must not 484 * be {@code null}. 485 * @param defaultValue The default return value if the parameter 486 * doesn't exist. May be {@code null}. 487 * 488 * @return The parameter value. 489 * 490 * @throws JSONRPC2Error On a bad parameter type or {@code null} value 491 * ({@link JSONRPC2Error#INVALID_PARAMS}). 492 */ 493 public <T> T getOpt(final int position, final Class<T> clazz, final T defaultValue) 494 throws JSONRPC2Error { 495 496 return getOpt(position, clazz, false, defaultValue); 497 } 498 499 500 /** 501 * Retrieves the specified optional parameter which must map to the 502 * provided class (use the appropriate wrapper class for primitive 503 * types). If the parameter doesn't exist the method returns the 504 * specified default value. 505 * 506 * @param position The parameter position. 507 * @param clazz The corresponding Java class that the parameter 508 * should map to (any one of the return types of 509 * the {@code getXXX()} getter methods. Set to 510 * {@code Object.class} to allow any type. Must not 511 * be {@code null}. 512 * @param allowNull If {@code true} allows a {@code null} parameter 513 * value. 514 * @param defaultValue The default return value if the parameter 515 * doesn't exist. May be {@code null}. 516 * 517 * @return The parameter value. 518 * 519 * @throws JSONRPC2Error On a bad parameter type 520 * ({@link JSONRPC2Error#INVALID_PARAMS}). 521 */ 522 @SuppressWarnings("unchecked") 523 public <T> T getOpt(final int position, 524 final Class<T> clazz, 525 final boolean allowNull, 526 final T defaultValue) 527 throws JSONRPC2Error { 528 529 if (! hasParameter(position)) 530 return defaultValue; 531 532 ensureParameter(position, clazz, allowNull); 533 534 try { 535 return (T)params.get(position); 536 537 } catch (ClassCastException e) { 538 539 throw newUnexpectedParameterTypeException(position); 540 } 541 } 542 543 544 /** 545 * Retrieves the specified string parameter. 546 * 547 * @param position The parameter position. 548 * 549 * @return The parameter value as a string. 550 * 551 * @throws JSONRPC2Error On a missing parameter, bad type or 552 * {@code null} value 553 * ({@link JSONRPC2Error#INVALID_PARAMS}). 554 */ 555 public String getString(final int position) 556 throws JSONRPC2Error { 557 558 return getString(position, false); 559 } 560 561 562 /** 563 * Retrieves the specified string parameter. 564 * 565 * @param position The parameter position. 566 * @param allowNull If {@code true} allows a {@code null} value. 567 * 568 * @return The parameter value as a string. 569 * 570 * @throws JSONRPC2Error On a missing parameter or bad type 571 * ({@link JSONRPC2Error#INVALID_PARAMS}). 572 */ 573 public String getString(final int position, final boolean allowNull) 574 throws JSONRPC2Error { 575 576 return get(position, String.class, allowNull); 577 } 578 579 580 /** 581 * Retrieves the specified optional string parameter. If it doesn't 582 * exist the method will return the specified default value. 583 * 584 * @param position The parameter position. 585 * @param defaultValue The default return value if the parameter 586 * doesn't exist. May be {@code null}. 587 * 588 * @return The parameter value as a string. 589 * 590 * @throws JSONRPC2Error On a bad type or {@code null} value 591 * ({@link JSONRPC2Error#INVALID_PARAMS}). 592 */ 593 public String getOptString(final int position, final String defaultValue) 594 throws JSONRPC2Error { 595 596 return getOptString(position, false, defaultValue); 597 } 598 599 600 /** 601 * Retrieves the specified optional string parameter. If it doesn't 602 * exist the method will return the specified default value. 603 * 604 * @param position The parameter position. 605 * @param allowNull If {@code true} allows a {@code null} value. 606 * @param defaultValue The default return value if the parameter 607 * doesn't exist. May be {@code null}. 608 * 609 * @return The parameter value as a string. 610 * 611 * @throws JSONRPC2Error On a bad type ({@link JSONRPC2Error#INVALID_PARAMS}). 612 */ 613 public String getOptString(final int position, final boolean allowNull, final String defaultValue) 614 throws JSONRPC2Error { 615 616 return getOpt(position, String.class, allowNull, defaultValue); 617 } 618 619 620 /** 621 * Retrieves the specified enumerated string parameter. 622 * 623 * @param position The parameter position. 624 * @param enumStrings The acceptable string values. Must not be 625 * {@code null}. 626 * 627 * @return The parameter value as a string. 628 * 629 * @throws JSONRPC2Error On a missing parameter, bad type or 630 * bad enumeration value 631 * ({@link JSONRPC2Error#INVALID_PARAMS}). 632 */ 633 public String getEnumString(final int position, final String[] enumStrings) 634 throws JSONRPC2Error { 635 636 return getEnumString(position, enumStrings, false); 637 } 638 639 640 /** 641 * Retrieves the specified enumerated string parameter, allowing for a 642 * case insenstive match. 643 * 644 * @param position The parameter position. 645 * @param enumStrings The acceptable string values. Must not be 646 * {@code null}. 647 * @param ignoreCase {@code true} for a case insensitive match. 648 * 649 * @return The matching parameter value as a string. 650 * 651 * @throws JSONRPC2Error On a missing parameter, bad type or 652 * bad enumeration value 653 * ({@link JSONRPC2Error#INVALID_PARAMS}). 654 */ 655 public String getEnumString(final int position, 656 final String[] enumStrings, 657 final boolean ignoreCase) 658 throws JSONRPC2Error { 659 660 String value = get(position, String.class); 661 662 String match = getEnumStringMatch(value, enumStrings, ignoreCase); 663 664 if (match == null) 665 throwEnumParameterException(position, enumStrings); 666 667 return match; 668 } 669 670 671 /** 672 * Retrieves the specified optional enumerated string parameter. If it 673 * doesn't exist the method will return the specified default value. 674 * 675 * @param position The parameter position. 676 * @param enumStrings The acceptable string values. Must not be 677 * {@code null}. 678 * @param defaultValue The default return value if the parameter 679 * doesn't exist. May be {@code null}. 680 * 681 * @return The parameter value as a string. 682 * 683 * @throws JSONRPC2Error On a bad type or bad enumeration value 684 * ({@link JSONRPC2Error#INVALID_PARAMS}). 685 */ 686 public String getOptEnumString(final int position, 687 final String[] enumStrings, 688 final String defaultValue) 689 throws JSONRPC2Error { 690 691 return getOptEnumString(position, enumStrings, defaultValue, false); 692 } 693 694 695 /** 696 * Retrieves the specified optional enumerated string parameter, 697 * allowing for a case insenstive match. If it doesn't exist the method 698 * will return the specified default value. 699 * 700 * @param position The parameter position. 701 * @param enumStrings The acceptable string values. Must not be 702 * {@code null}. 703 * @param defaultValue The default return value if the parameter 704 * doesn't exist. May be {@code null}. 705 * @param ignoreCase {@code true} for a case insensitive match. 706 * 707 * @return The parameter value as a string. 708 * 709 * @throws JSONRPC2Error On a bad type or bad enumeration value 710 * ({@link JSONRPC2Error#INVALID_PARAMS}). 711 */ 712 public String getOptEnumString(final int position, 713 final String[] enumStrings, 714 final String defaultValue, 715 final boolean ignoreCase) 716 throws JSONRPC2Error { 717 718 String value = getOpt(position, String.class, defaultValue); 719 720 if (defaultValue == null && value == null) 721 return null; 722 723 String match = getEnumStringMatch(value, enumStrings, ignoreCase); 724 725 if (match == null) 726 throwEnumParameterException(position, enumStrings); 727 728 return match; 729 } 730 731 732 /** 733 * Retrieves the specified enumerated parameter (from a JSON string 734 * that has a predefined set of possible values). 735 * 736 * @param position The parameter position. 737 * @param enumClass An enumeration type with constant names 738 * representing the acceptable string values. Must not 739 * be {@code null}. 740 * 741 * @return The matching enumeration constant. 742 * 743 * @throws JSONRPC2Error On a missing parameter, bad type or 744 * bad enumeration value 745 * ({@link JSONRPC2Error#INVALID_PARAMS}). 746 */ 747 public <T extends Enum<T>> T getEnum(final int position, final Class<T> enumClass) 748 throws JSONRPC2Error { 749 750 return getEnum(position, enumClass, false); 751 } 752 753 754 /** 755 * Retrieves the specified enumerated parameter (from a JSON string 756 * that has a predefined set of possible values), allowing for a case 757 * insensitive match. 758 * 759 * @param position The parameter position. 760 * @param enumClass An enumeration type with constant names 761 * representing the acceptable string values. Must 762 * not be {@code null}. 763 * @param ignoreCase If {@code true} a case insensitive match against 764 * the acceptable constant names is performed. 765 * 766 * @return The matching enumeration constant. 767 * 768 * @throws JSONRPC2Error On a missing parameter, bad type or 769 * bad enumeration value 770 * ({@link JSONRPC2Error#INVALID_PARAMS}). 771 */ 772 public <T extends Enum<T>> T getEnum(final int position, 773 final Class<T> enumClass, 774 final boolean ignoreCase) 775 throws JSONRPC2Error { 776 777 String value = get(position, String.class); 778 779 T match = getEnumStringMatch(value, enumClass, ignoreCase); 780 781 if (match == null) 782 throwEnumParameterException(position, enumClass); 783 784 return match; 785 } 786 787 788 /** 789 * Retrieves the specified optional enumerated parameter (from a JSON 790 * string that has a predefined set of possible values). If it doesn't 791 * exist the method will return the specified default value. 792 * 793 * @param position The parameter position. 794 * @param enumClass An enumeration type with constant names 795 * representing the acceptable string values. Must 796 * not be {@code null}. 797 * @param defaultValue The default return value if the parameter 798 * doesn't exist. May be {@code null}. 799 * 800 * @return The matching enumeration constant. 801 * 802 * @throws JSONRPC2Error On a bad type or bad enumeration value 803 * ({@link JSONRPC2Error#INVALID_PARAMS}). 804 */ 805 public <T extends Enum<T>> T getOptEnum(final int position, 806 final Class<T> enumClass, 807 final String defaultValue) 808 throws JSONRPC2Error { 809 810 return getOptEnum(position, enumClass, defaultValue, false); 811 } 812 813 814 /** 815 * Retrieves the specified optional enumerated parameter (from a JSON 816 * string that has a predefined set of possible values), allowing for a 817 * case insenstive match. If it doesn't exist the method will return 818 * the specified default value. 819 * 820 * @param position The parameter position. 821 * @param enumClass An enumeration type with constant names 822 * representing the acceptable string values. Must 823 * not be {@code null}. 824 * @param defaultValue The default return value if the parameter 825 * doesn't exist. May be {@code null}. 826 * @param ignoreCase If {@code true} a case insensitive match against 827 * the acceptable constant names is performed. 828 * 829 * @return The matching enumeration constant. 830 * 831 * @throws JSONRPC2Error On a bad type or bad enumeration value 832 * ({@link JSONRPC2Error#INVALID_PARAMS}). 833 */ 834 public <T extends Enum<T>> T getOptEnum(final int position, 835 final Class<T> enumClass, 836 final String defaultValue, 837 final boolean ignoreCase) 838 throws JSONRPC2Error { 839 840 String value = getOpt(position, String.class, defaultValue); 841 842 if (defaultValue == null && value == null) 843 return null; 844 845 T match = getEnumStringMatch(value, enumClass, ignoreCase); 846 847 if (match == null) 848 throwEnumParameterException(position, enumClass); 849 850 return match; 851 } 852 853 854 /** 855 * Retrieves the specified boolean (maps from JSON true/false) 856 * parameter. 857 * 858 * @param position The parameter position. 859 * 860 * @return The parameter value as a {@code boolean}. 861 * 862 * @throws JSONRPC2Error On a missing parameter, bad type or 863 * {@code null} value 864 * ({@link JSONRPC2Error#INVALID_PARAMS}). 865 */ 866 public boolean getBoolean(final int position) 867 throws JSONRPC2Error { 868 869 return get(position, Boolean.class); 870 } 871 872 873 /** 874 * Retrieves the specified optional boolean (maps from JSON true/false) 875 * parameter. If it doesn't exist the method will return the specified 876 * default value. 877 * 878 * @param position The parameter position. 879 * @param defaultValue The default return value if the parameter 880 * doesn't exist. 881 * 882 * @return The parameter value as a {@code boolean}. 883 * 884 * @throws JSONRPC2Error On a bad parameter type or {@code null} value 885 * ({@link JSONRPC2Error#INVALID_PARAMS}). 886 */ 887 public boolean getOptBoolean(final int position, final boolean defaultValue) 888 throws JSONRPC2Error { 889 890 return getOpt(position, Boolean.class, defaultValue); 891 } 892 893 894 /** 895 * Retrieves the specified numeric parameter as an {@code int}. 896 * 897 * @param position The parameter position. 898 * 899 * @return The parameter value as an {@code int}. 900 * 901 * @throws JSONRPC2Error On a missing parameter, bad type or 902 * {@code null} value 903 * ({@link JSONRPC2Error#INVALID_PARAMS}). 904 */ 905 public int getInt(final int position) 906 throws JSONRPC2Error { 907 908 Number number = get(position, Number.class); 909 return number.intValue(); 910 } 911 912 913 /** 914 * Retrieves the specified optional numeric parameter as an 915 * {@code int}. If it doesn't exist the method will return the 916 * specified default value. 917 * 918 * @param position The parameter position. 919 * @param defaultValue The default return value if the parameter 920 * doesn't exist. 921 * 922 * @return The parameter value as an {@code int}. 923 * 924 * @throws JSONRPC2Error On a bad parameter type or {@code null} value 925 * ({@link JSONRPC2Error#INVALID_PARAMS}). 926 */ 927 public int getOptInt(final int position, final int defaultValue) 928 throws JSONRPC2Error { 929 930 Number number = getOpt(position, Number.class, defaultValue); 931 return number.intValue(); 932 } 933 934 935 /** 936 * Retrieves the specified numeric parameter as a {@code long}. 937 * 938 * @param position The parameter position. 939 * 940 * @return The parameter value as a {@code long}. 941 * 942 * @throws JSONRPC2Error On a missing parameter, bad type or 943 * {@code null} value 944 * ({@link JSONRPC2Error#INVALID_PARAMS}). 945 */ 946 public long getLong(final int position) 947 throws JSONRPC2Error { 948 949 Number number = get(position, Number.class); 950 return number.longValue(); 951 } 952 953 954 /** 955 * Retrieves the specified optional numeric parameter as a 956 * {@code long}. If it doesn't exist the method will return the 957 * specified default value. 958 * 959 * @param position The parameter position. 960 * @param defaultValue The default return value if the parameter 961 * doesn't exist. 962 * 963 * @return The parameter value as a {@code long}. 964 * 965 * @throws JSONRPC2Error On a bad parameter type or {@code null} value 966 * ({@link JSONRPC2Error#INVALID_PARAMS}). 967 */ 968 public long getOptLong(final int position, final long defaultValue) 969 throws JSONRPC2Error { 970 971 Number number = getOpt(position, Number.class, defaultValue); 972 return number.longValue(); 973 } 974 975 976 /** 977 * Retrieves the specified numeric parameter as a {@code float}. 978 * 979 * @param position The parameter position. 980 * 981 * @return The parameter value as a {@code float}. 982 * 983 * @throws JSONRPC2Error On a missing parameter, bad type or 984 * {@code null} value 985 * ({@link JSONRPC2Error#INVALID_PARAMS}). 986 */ 987 public float getFloat(final int position) 988 throws JSONRPC2Error { 989 990 Number number = get(position, Number.class); 991 return number.floatValue(); 992 } 993 994 995 /** 996 * Retrieves the specified optional numeric parameter as a 997 * {@code float}. If it doesn't exist the method will return the 998 * specified default value. 999 * 1000 * @param position The parameter position. 1001 * @param defaultValue The default return value if the parameter 1002 * doesn't exist. 1003 * 1004 * @return The parameter value as a {@code float}. 1005 * 1006 * @throws JSONRPC2Error On a bad parameter type or {@code null} value 1007 * ({@link JSONRPC2Error#INVALID_PARAMS}). 1008 */ 1009 public float getOptFloat(final int position, final float defaultValue) 1010 throws JSONRPC2Error { 1011 1012 Number number = getOpt(position, Number.class, defaultValue); 1013 return number.floatValue(); 1014 } 1015 1016 1017 /** 1018 * Retrieves the specified numeric parameter as a {@code double}. 1019 * 1020 * @param position The parameter position. 1021 * 1022 * @return The parameter value as a {@code double}. 1023 * 1024 * @throws JSONRPC2Error On a missing parameter, bad type or 1025 * {@code null} value 1026 * ({@link JSONRPC2Error#INVALID_PARAMS}). 1027 */ 1028 public double getDouble(final int position) 1029 throws JSONRPC2Error { 1030 1031 Number number = get(position, Number.class); 1032 return number.doubleValue(); 1033 } 1034 1035 1036 /** 1037 * Retrieves the specified optional numeric parameter as a 1038 * {@code double}. If it doesn't exist the method will return the 1039 * specified default value. 1040 * 1041 * @param position The parameter position. 1042 * @param defaultValue The default return value if the parameter 1043 * doesn't exist. 1044 * 1045 * @return The parameter value as a {@code double}. 1046 * 1047 * @throws JSONRPC2Error On a bad parameter type or {@code null} value 1048 * ({@link JSONRPC2Error#INVALID_PARAMS}). 1049 */ 1050 public double getOptDouble(final int position, final double defaultValue) 1051 throws JSONRPC2Error { 1052 1053 Number number = getOpt(position, Number.class, defaultValue); 1054 return number.doubleValue(); 1055 } 1056 1057 1058 /** 1059 * Retrieves the specified list (maps from JSON array) parameter. 1060 * 1061 * @param position The parameter position. 1062 * 1063 * @return The parameter value as a list. 1064 * 1065 * @throws JSONRPC2Error On a missing parameter, bad type or 1066 * {@code null} value 1067 * ({@link JSONRPC2Error#INVALID_PARAMS}). 1068 */ 1069 public List<Object> getList(final int position) 1070 throws JSONRPC2Error { 1071 1072 final boolean allowNull = false; 1073 1074 return getList(position, allowNull); 1075 } 1076 1077 1078 /** 1079 * Retrieves the specified list (maps from JSON array) parameter. 1080 * 1081 * @param position The parameter position. 1082 * @param allowNull If {@code true} allows a {@code null} value. 1083 * 1084 * @return The parameter value as a list. 1085 * 1086 * @throws JSONRPC2Error On a missing parameter or bad type 1087 * ({@link JSONRPC2Error#INVALID_PARAMS}). 1088 */ 1089 @SuppressWarnings("unchecked") 1090 public List<Object> getList(final int position, final boolean allowNull) 1091 throws JSONRPC2Error { 1092 1093 return (List<Object>)get(position, List.class, allowNull); 1094 } 1095 1096 1097 /** 1098 * Retrieves the specified optional list (maps from JSON array) 1099 * parameter. If it doesn't exist the method will return the specified 1100 * default value. 1101 * 1102 * @param position The parameter position. 1103 * @param defaultValue The default return value if the parameter 1104 * doesn't exist. May be {@code null}. 1105 * 1106 * @return The parameter value as a list. 1107 * 1108 * @throws JSONRPC2Error On a bad parameter type or {@code null} value 1109 * ({@link JSONRPC2Error#INVALID_PARAMS}). 1110 */ 1111 public List<Object> getOptList(final int position, final List<Object> defaultValue) 1112 throws JSONRPC2Error { 1113 1114 final boolean allowNull = false; 1115 1116 return getOptList(position, allowNull, defaultValue); 1117 } 1118 1119 1120 /** 1121 * Retrieves the specified optional list (maps from JSON array) 1122 * parameter. If it doesn't exist the method will return the specified 1123 * default value. 1124 * 1125 * @param position The parameter position. 1126 * @param allowNull If {@code true} allows a {@code null} value. 1127 * @param defaultValue The default return value if the parameter 1128 * doesn't exist. May be {@code null}. 1129 * 1130 * @return The parameter value as a list. 1131 * 1132 * @throws JSONRPC2Error On a bad parameter type 1133 * ({@link JSONRPC2Error#INVALID_PARAMS}). 1134 */ 1135 @SuppressWarnings("unchecked") 1136 public List<Object> getOptList(final int position, 1137 final boolean allowNull, 1138 final List<Object> defaultValue) 1139 throws JSONRPC2Error { 1140 1141 return (List<Object>)getOpt(position, List.class, allowNull, defaultValue); 1142 } 1143 1144 1145 /** 1146 * Retrieves the specified string array (maps from JSON array of 1147 * strings) parameter. 1148 * 1149 * @param position The parameter position. 1150 * 1151 * @return The parameter value as a string array. 1152 * 1153 * @throws JSONRPC2Error On a missing parameter, bad type or 1154 * {@code null} value 1155 * ({@link JSONRPC2Error#INVALID_PARAMS}). 1156 */ 1157 public String[] getStringArray(final int position) 1158 throws JSONRPC2Error { 1159 1160 final boolean allowNull = false; 1161 1162 return getStringArray(position, allowNull); 1163 } 1164 1165 1166 /** 1167 * Retrieves the specified string array (maps from JSON array of 1168 * strings) parameter. 1169 * 1170 * @param position The parameter position. 1171 * @param allowNull If {@code true} allows a {@code null} value. 1172 * 1173 * @return The parameter value as a string array. 1174 * 1175 * @throws JSONRPC2Error On a missing parameter or bad type 1176 * ({@link JSONRPC2Error#INVALID_PARAMS}). 1177 */ 1178 @SuppressWarnings("unchecked") 1179 public String[] getStringArray(final int position, final boolean allowNull) 1180 throws JSONRPC2Error { 1181 1182 List<Object> list = getList(position, allowNull); 1183 1184 if (list == null) 1185 return null; 1186 1187 try { 1188 return list.toArray(new String[list.size()]); 1189 1190 } catch (ArrayStoreException e) { 1191 1192 throw newArrayException(position); 1193 } 1194 } 1195 1196 1197 /** 1198 * Retrieves the specified optional string array (maps from JSON array 1199 * of strings) parameter. If it doesn't exist the method will return 1200 * the specified default value. 1201 * 1202 * @param position The parameter position. 1203 * @param defaultValue The default return value if the parameter 1204 * doesn't exist. May be {@code null}. 1205 * 1206 * @return The parameter value as a string array. 1207 * 1208 * @throws JSONRPC2Error On a bad parameter type or {@code null} value 1209 * ({@link JSONRPC2Error#INVALID_PARAMS}). 1210 */ 1211 public String[] getOptStringArray(final int position, final String[] defaultValue) 1212 throws JSONRPC2Error { 1213 1214 final boolean allowNull = false; 1215 1216 return getOptStringArray(position, allowNull, defaultValue); 1217 } 1218 1219 1220 /** 1221 * Retrieves the specified optional string array (maps from JSON array 1222 * of strings) parameter. If it doesn't exist the method will return 1223 * the specified default value. 1224 * 1225 * @param position The parameter position. 1226 * @param allowNull If {@code true} allows a {@code null} value. 1227 * @param defaultValue The default return value if the parameter 1228 * doesn't exist. May be {@code null}. 1229 * 1230 * @return The parameter value as a string array. 1231 * 1232 * @throws JSONRPC2Error On a bad parameter type 1233 * ({@link JSONRPC2Error#INVALID_PARAMS}). 1234 */ 1235 public String[] getOptStringArray(final int position, 1236 final boolean allowNull, 1237 final String[] defaultValue) 1238 throws JSONRPC2Error { 1239 1240 if (! hasParameter(position)) 1241 return defaultValue; 1242 1243 return getStringArray(position, allowNull); 1244 } 1245 1246 1247 /** 1248 * Retrieves the specified map (maps from JSON object) parameter. 1249 * 1250 * @param position The parameter position. 1251 * 1252 * @return The parameter value as a map. 1253 * 1254 * @throws JSONRPC2Error On a missing parameter, bad type or 1255 * {@code null} value 1256 * ({@link JSONRPC2Error#INVALID_PARAMS}). 1257 */ 1258 public Map<String,Object> getMap(final int position) 1259 throws JSONRPC2Error { 1260 1261 return getMap(position, false); 1262 } 1263 1264 1265 /** 1266 * Retrieves the specified map (maps from JSON object) parameter. 1267 * 1268 * @param position The parameter position. 1269 * @param allowNull If {@code true} allows a {@code null} value. 1270 * 1271 * @return The parameter value as a map. 1272 * 1273 * @throws JSONRPC2Error On a missing parameter or bad type 1274 * ({@link JSONRPC2Error#INVALID_PARAMS}). 1275 */ 1276 @SuppressWarnings("unchecked") 1277 public Map<String,Object> getMap(final int position, final boolean allowNull) 1278 throws JSONRPC2Error { 1279 1280 try { 1281 return (Map<String,Object>)get(position, Map.class, allowNull); 1282 1283 } catch (ClassCastException e) { 1284 1285 throw newUnexpectedParameterTypeException(position); 1286 } 1287 } 1288 1289 1290 /** 1291 * Retrieves the specified optional map (maps from JSON object) 1292 * parameter. If it doesn't exist the method will return the specified 1293 * default value. 1294 * 1295 * @param position The parameter position. 1296 * @param defaultValue The default return value if the parameter 1297 * doesn't exist. May be {@code null}. 1298 * 1299 * @return The parameter value as a map. 1300 * 1301 * @throws JSONRPC2Error On a bad parameter type or {@code null} value 1302 * ({@link JSONRPC2Error#INVALID_PARAMS}). 1303 */ 1304 public Map<String,Object> getOptMap(final int position, final Map<String,Object> defaultValue) 1305 throws JSONRPC2Error { 1306 1307 return getOptMap(position, false, defaultValue); 1308 } 1309 1310 1311 /** 1312 * Retrieves the specified optional map (maps from JSON object) 1313 * parameter. If it doesn't exist the method will return the specified 1314 * default value. 1315 * 1316 * @param position The parameter position. 1317 * @param allowNull If {@code true} allows a {@code null} value. 1318 * @param defaultValue The default return value if the parameter 1319 * doesn't exist. May be {@code null}. 1320 * 1321 * @return The parameter value as a map. 1322 * 1323 * @throws JSONRPC2Error On a bad parameter type 1324 * ({@link JSONRPC2Error#INVALID_PARAMS}). 1325 */ 1326 @SuppressWarnings("unchecked") 1327 public Map<String,Object> getOptMap(final int position, 1328 final boolean allowNull, 1329 final Map<String,Object> defaultValue) 1330 throws JSONRPC2Error { 1331 1332 try { 1333 return (Map<String,Object>)getOpt(position, Map.class, allowNull, defaultValue); 1334 1335 } catch (ClassCastException e) { 1336 1337 throw newUnexpectedParameterTypeException(position); 1338 } 1339 } 1340}