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