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