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