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