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