001package Torello.Java.JSON; 002 003import javax.json.*; 004import java.math.*; 005 006import static javax.json.JsonValue.ValueType.*; 007import static Torello.Java.JSON.JFlag.*; 008 009import java.util.function.Function; 010 011/** 012 * Class which provides a series of helper functions for all JSON Type-Binding Reader 013 * Classes. 014 * 015 * <BR /><BR /><B CLASS=JDDescLabel>IMPORTANT:</B> 016 * <BR />100% of the helper-methods that appear here are protected, and cannot be accessed 017 * outside of this package. They are included in the documentation solely for the purposes of 018 * (<I>if you happen to be interested</I>) letting you know how the JSON-Tools work. <I>It is not 019 * intended that programmers would ever need to invoke, directly, any of the methods in this 020 * class!</I> 021 */ 022@Torello.JavaDoc.StaticFunctional 023public class RJInternal 024{ 025 private RJInternal() { } 026 027 028 // ******************************************************************************************** 029 // ******************************************************************************************** 030 // "Helpers for the Helpers for the Helpers" 031 // ******************************************************************************************** 032 // ******************************************************************************************** 033 034 035 /** 036 * Generates a {@code JsonException} with a uniformly-consisten error-message. 037 038 protected static void throwJsonBindingException(Class<?> c) 039 { 040 throw new JsonException( 041 "The class which was passed to parameter 'c' [" + c.getName() + "] does not " + 042 "appear to have a constructor with precisely one parameter of type JsonObject." 043 ); 044 } 045 */ 046 047 /** 048 * Helper Method that generates an {@code ArithmeticException} with a uniformly-consistent 049 * exception message 050 * @param jn A Java {@code javax.json.JsonNumber} whose magnitude is too large. 051 * @throws ArithmeticException 052 */ 053 protected static void throwAE_INFINITY 054 (JsonNumber jn, String primTypeName, boolean positiveOrNegative) 055 { 056 throw new ArithmeticException( 057 "When attempting to conver the JsonNumber [" + jn.toString() + "] to a " + 058 primTypeName + " primitive, the number had a magnitude that was too large: " + 059 (positiveOrNegative ? "Positive" : "Negative") + " Infinity was returned." 060 ); 061 } 062 063 /** 064 * Helper Method that generates an {@code ArithmeticException} with a uniformly-consistent 065 * exception message 066 * @param bd A Java {@code java.math.BigDecimal} whose magnitude is too large. 067 * @throws ArithmeticException 068 */ 069 protected static void throwAE_INFINITY(BigDecimal bd, String primTypeName) 070 { 071 throw new ArithmeticException( 072 "When attempting to conver the JsonNumber [" + bd.toString() + "] to a " + 073 primTypeName + " primitive, the number had a magnitude that was infinite." 074 ); 075 } 076 /** 077 * Helper Method that generates an {@code ArithmeticException} with a uniformly-consistent 078 * exception message 079 * @param bd A Java {@code java.math.BigDecimal} with a loss of precision. 080 * @throws ArithmeticException 081 */ 082 protected static void throwAE_PRECISION(BigDecimal bd, String primTypeName) 083 { 084 throw new ArithmeticException( 085 "When attempting to conver the JsonNumber [" + bd.toString() + "] to a " + 086 primTypeName + " primitive, the number had a loss of precision." 087 ); 088 } 089 090 /** 091 * Converts a {@link JsonNumber} into a Java {@code double} 092 * @param jn Any {@link JsonNumber} 093 * @return java {@code double} primitive 094 * @throws JsonArithmeticException If infinity is returned from the call to 095 * {@code BigDecimal.doubleValue()} 096 * @see JsonNumber#bigDecimalValue() 097 */ 098 protected static double DOUBLE_WITH_CHECK(JsonNumber jn) 099 { return DOUBLE_WITH_CHECK(jn.bigDecimalValue()); } 100 101 /** 102 * Converts a {@code BigDecimal} into a Java {@code double} 103 * @param bd Any {@code BigDecimal} 104 * @return Java {@code double} primitive 105 * @throws JsonArithmeticException If infinity is returned from the call to 106 * {@code code BigDecimal.doubleValue()} 107 */ 108 protected static double DOUBLE_WITH_CHECK(BigDecimal bd) 109 { 110 double ret = bd.doubleValue(); 111 112 if (Double.isInfinite(ret)) throwAE_INFINITY(bd, "double"); 113 114 if (BigDecimal.valueOf(ret).compareTo(bd) != 0) throwAE_PRECISION(bd, "double"); 115 116 return ret; 117 } 118 119 /** 120 * Converts a {@link JsonNumber} into a Java {@code float} 121 * @param jn Any {@link JsonNumber} 122 * @return java {@code float} primitive 123 * @throws JsonArithmeticException If infinity is returned from the call to 124 * {@code BigDecimal.floatValue()} 125 * @see JsonNumber#bigDecimalValue() 126 */ 127 protected static float FLOAT_WITH_CHECK(JsonNumber jn) 128 { return FLOAT_WITH_CHECK(jn.bigDecimalValue()); } 129 130 /** 131 * Converts a {@code BigDecimal} into a Java {@code float} 132 * @param bd Any {@code BigDecimal} 133 * @return Java {@code float} primitive 134 * @throws JsonArithmeticException If infinity is returned from the call to 135 * {@code code BigDecimal.floatValue()} 136 */ 137 protected static float FLOAT_WITH_CHECK(BigDecimal bd) 138 { 139 float ret = bd.floatValue(); 140 141 if (Float.isInfinite(ret)) throwAE_INFINITY(bd, "float"); 142 143 if (BigDecimal.valueOf(ret).compareTo(bd) != 0) throwAE_PRECISION(bd, "float"); 144 145 return ret; 146 } 147 148 /** 149 * Converts any {@link JsonNumber} into one of the inheriting subclasses of Java class 150 * {@code Number} 151 * @param jn Any {@link JsonNumber} 152 * @return The most appropriate intance of {@code java.lang.Number} 153 * @see ReadNumberJSON#get(JsonObject, String, int, Number) 154 * @see ReadNumberJSON#get(JsonArray, int, int, Number) 155 * @see JsonNumber#isIntegral() 156 * @see JsonNumber#bigIntegerValue() 157 * @see JsonNumber#bigDecimalValue() 158 */ 159 protected static Number convertToNumber(JsonNumber jn) 160 { 161 if (jn.isIntegral()) 162 { 163 BigInteger bi = jn.bigIntegerValue(); 164 int l = bi.bitLength(); 165 166 if (l <= 32) return Integer.valueOf(bi.intValue()); 167 if (l <= 64) return Long.valueOf(bi.longValue()); 168 169 return bi; 170 } 171 172 else 173 { 174 BigDecimal bd = jn.bigDecimalValue(); 175 176 // This probably isn't the most efficient thing I've ever written, but I do not 177 // have the energy to stare at java.math.BigDecimal at the moment. The JavaDoc for 178 // this JSON => Java-Type Conversion is quite intricate. I will figure this out at 179 // at later date. 180 181 float f = bd.floatValue(); 182 183 if ( (! Float.isInfinite(f)) 184 && (BigDecimal.valueOf(f).compareTo(bd) == 0) 185 ) 186 return (Float) f; 187 188 double d = bd.doubleValue(); 189 190 if ( (! Double.isInfinite(d)) 191 && (BigDecimal.valueOf(d).compareTo(bd) == 0) 192 ) 193 return (Double) d; 194 195 return bd; 196 } 197 } 198 199 /** 200 * Converts any {@code java.lang.String} into one of the inheriting subclasses of Java class 201 * {@code Number} 202 * @param s Any {@code String} 203 * @return The most appropriate instance of {@code java.lang.Number} 204 * @throws NumberFormatException If the input {@code String} isn't properly formatted as a 205 * number. 206 * @see ReadNumberJSON#parse(JsonObject, String, int, Number, Function) 207 * @see ReadNumberJSON#parse(JsonArray, int, int, Number, Function) 208 */ 209 protected static Number convertToNumber(String s) 210 { return convertToNumber(new BigDecimal(s.trim())); } 211 212 /** 213 * Converts any {@code java.math.BigDecimal} into one of the inheriting subclasses of 214 * {@code Number}. 215 * @param bd Any {@code BigDecimal} 216 * @return The most appropriate instance of {@code java.lang.Number} 217 */ 218 protected static Number convertToNumber(BigDecimal bd) 219 { 220 if (bd.scale() == 0) 221 { 222 BigInteger bi = bd.toBigInteger(); 223 int l = bi.bitLength(); 224 225 if (l <= 32) return Integer.valueOf(bi.intValue()); 226 if (l <= 64) return Long.valueOf(bi.longValue()); 227 return bi; 228 } 229 230 else 231 { 232 // This probably isn't the most efficient thing I've ever written, but I do not 233 // have the energy to stare at java.math.BigDecimal at the moment. The JavaDoc for 234 // this JSON => Java-Type Conversion is quite intricate. I will figure this out at 235 // at later date. 236 237 float f = bd.floatValue(); 238 239 if ( (! Float.isInfinite(f)) 240 && (BigDecimal.valueOf(f).compareTo(bd) == 0) 241 ) 242 return (Float) f; 243 244 double d = bd.doubleValue(); 245 246 if ( (! Double.isInfinite(d)) 247 && (BigDecimal.valueOf(d).compareTo(bd) == 0) 248 ) 249 return (Double) d; 250 251 return bd; 252 } 253 } 254 255 256 // ******************************************************************************************** 257 // ******************************************************************************************** 258 // PRIMARY FOUR "GET" METHODS FOR NUMBERS 259 // ******************************************************************************************** 260 // ******************************************************************************************** 261 262 263 /** 264 * This is an internal helper method for retrieving an element from a {@link JsonArray}, 265 * and converting it to one of the standard <B STYLE='color: red;'>Java Types</B>. 266 * 267 * @param <T> <EMBED CLASS='external-html' DATA-FILE-ID=JR_GET_T> 268 * @param ja Any instance of {@link JsonArray} 269 * @param index Any index into the array which holds a {@link JsonNumber} 270 * @param primitiveClass <EMBED CLASS='external-html' DATA-FILE-ID=JR_GET_PC> 271 * @param jsonTypeToJavaType <EMBED CLASS='external-html' DATA-FILE-ID=JR_GET_JTTJT> 272 * 273 * @return The converted number, as an instance Generic-Parameter {@code 'T'} 274 * 275 * @throws JsonNullPrimitiveArrException <EMBED CLASS='external-html' 276 * DATA-FILE-ID=JR_GET_JNPAEX> 277 * @throws JsonTypeArrException <EMBED CLASS='external-html' DATA-FILE-ID=JR_GET_JTAEX> 278 * @throws JsonArithmeticArrException If there any arithmetic problems during the conversion 279 * @throws IndexOutOfBoundsException If {@code 'index'} is out of the bounds of {@code 'ja'} 280 * 281 * @see ReadPrimJSON#getInt(JsonArray, int) 282 * @see ReadPrimJSON#getLong(JsonArray, int) 283 * @see ReadPrimJSON#getShort(JsonArray, int) 284 * @see ReadPrimJSON#getByte(JsonArray, int) 285 * @see ReadPrimJSON#getDouble(JsonArray, int) 286 * @see ReadPrimJSON#getFloat(JsonArray, int) 287 */ 288 protected static <T> T GET( 289 JsonArray ja, int index, Class<T> primitiveClass, 290 Function<JsonNumber, T> jsonTypeToJavaType 291 ) 292 { 293 // This will throw an IndexOutOfBoundsException if the index is out of bounds. 294 JsonValue jv = ja.get(index); 295 296 switch (jv.getValueType()) 297 { 298 // This method allows for null-returns. If Json-Null, return Java-Null. 299 case NULL: throw new JsonNullPrimitiveArrException 300 (ja, index, NUMBER, primitiveClass); 301 302 // This will throw ArithmeticException if it cannot be converted 303 case NUMBER: 304 305 // REMEMBER: The primary reason for this class is that MEANINGFUL ERROR MESSAGES 306 // make Json-Binding a lot easer... "JsonArithmeticException" has just 307 // about everything that you need to know when debugging this stuff 308 309 try 310 { return jsonTypeToJavaType.apply((JsonNumber) jv); } 311 312 catch (ArithmeticException ae) 313 { 314 throw new JsonArithmeticArrException 315 (ae, ja, index, NUMBER, jv, primitiveClass); 316 } 317 318 // The JsonValue at the specified array-index does not contain an JsonNumber. 319 default: throw new JsonTypeArrException 320 (ja, index, NUMBER, jv, primitiveClass); 321 } 322 } 323 324 /** 325 * This is an internal helper method for retrieving an element from a {@link JsonArray}, 326 * and converting it to one of the standard <B STYLE='color: red;'>Java Types</B>. 327 * 328 * @param <T> <EMBED CLASS='external-html' DATA-FILE-ID=JR_GET_T> 329 * @param ja Any instance of {@link JsonArray} 330 * @param index Any index into the array which holds a {@link JsonNumber} 331 * @param jsonTypeToJavaType <EMBED CLASS='external-html' DATA-FILE-ID=JR_GET_JTTJT> 332 * 333 * @return The converted number, as an instance Generic-Parameter {@code 'T'} 334 * 335 * @throws JsonTypeArrException <EMBED CLASS='external-html' DATA-FILE-ID=JR_GET_JTAEX> 336 * @throws JsonArithmeticArrException If there any arithmetic problems during the conversion 337 * @throws IndexOutOfBoundsException If {@code 'index'} is out of the bounds of {@code 'ja'} 338 * 339 * @see ReadBoxedJSON#getInteger(JsonArray, int) 340 * @see ReadBoxedJSON#getLong(JsonArray, int) 341 * @see ReadBoxedJSON#getShort(JsonArray, int) 342 * @see ReadBoxedJSON#getByte(JsonArray, int) 343 * @see ReadBoxedJSON#getDouble(JsonArray, int) 344 * @see ReadBoxedJSON#getFloat(JsonArray, int) 345 */ 346 protected static <T extends java.lang.Number> T GET 347 (JsonArray ja, int index, Function<JsonNumber, T> jsonTypeToJavaType, Class<T> returnClass) 348 { 349 // This will throw an IndexOutOfBoundsException if the index is out of bounds. 350 // Since this *IS NOT* a method with FLAGS, the user has no way to avoid this exception 351 // throw if, indeed, the index really is out of bounds! 352 // 353 // Using one of the 'FLAGS' variants of the 'GET' array-index, a user may request that 354 // either null or a default-value be returned. Not with this version-of 'GET', though. 355 356 JsonValue jv = ja.get(index); 357 358 switch (jv.getValueType()) 359 { 360 // This method allows for null-returns. If Json-Null, return Java-Null. 361 case NULL: return null; 362 363 // This will throw ArithmeticException if it cannot be converted 364 case NUMBER: 365 366 // REMEMBER: The primary reason for this class is that MEANINGFUL ERROR MESSAGES 367 // make Json-Binding a lot easer... "JsonArithmeticException" has just 368 // about everything that you need to know when debugging this stuff 369 370 try 371 { return jsonTypeToJavaType.apply((JsonNumber) jv); } 372 373 catch (ArithmeticException ae) 374 { 375 throw new JsonArithmeticArrException 376 (ae, ja, index, NUMBER, jv, returnClass); 377 } 378 379 // The JsonValue at the specified array-index does not contain an JsonNumber. 380 default: throw new JsonTypeArrException 381 (ja, index, NUMBER, jv, returnClass); 382 } 383 } 384 385 /** 386 * This is an internal helper method for retrieving a property from a {@link JsonObject}, 387 * and converting it to one of the standard <B STYLE='color: red;'>Java Types</B>. 388 * 389 * @param <T> <EMBED CLASS='external-html' DATA-FILE-ID=JR_GET_T> 390 * @param jo Any instance of {@link JsonObject} 391 * @param propertyName Any property name contained by {@code 'jo'} 392 * @param jsonTypeToJavaType <EMBED CLASS='external-html' DATA-FILE-ID=JR_GET_JTTJT> 393 * 394 * @return The converted number, as an instance Generic-Parameter {@code 'T'} 395 * 396 * @throws JsonNullPrimitiveObjException <EMBED CLASS='external-html' 397 * DATA-FILE-ID=JR_GET_JNPOEX> 398 * @throws JsonPropMissingException If the property is missing, and {@code 'isOptional'} 399 * is {@code FALSE}. 400 * @throws JsonTypeObjException <EMBED CLASS='external-html' DATA-FILE-ID=JR_GET_JTAEX> 401 * @throws JsonArithmeticObjException If there any arithmetic problems during the conversion 402 * 403 * @see ReadPrimJSON#getInt(JsonObject, String) 404 * @see ReadPrimJSON#getLong(JsonObject, String) 405 * @see ReadPrimJSON#getShort(JsonObject, String) 406 * @see ReadPrimJSON#getByte(JsonObject, String) 407 * @see ReadPrimJSON#getDouble(JsonObject, String) 408 * @see ReadPrimJSON#getFloat(JsonObject, String) 409 */ 410 protected static <T> T GET( 411 JsonObject jo, String propertyName, Class<T> primitiveClass, 412 Function<JsonNumber, T> jsonTypeToJavaType 413 ) 414 { 415 // Here, a 'get' request was made for a property that isn't actually listed among the 416 // properties in the provided JsonObject. Since this internal 'GET' is used by methods 417 // that are trying to return a Java Primitive (like 'int' or 'float'), then an exception 418 // has to be thrown. The option of returning 'null' isn't possible here! 419 420 if (! jo.containsKey(propertyName)) throw new JsonPropMissingException 421 (jo, propertyName, NUMBER, primitiveClass); 422 423 JsonValue jv = jo.get(propertyName); 424 425 switch (jv.getValueType()) 426 { 427 // This method allows for null-returns. If Json-Null, return Java-Null. 428 case NULL: throw new JsonNullPrimitiveObjException 429 (jo, propertyName, NUMBER, primitiveClass); 430 431 // This will throw ArithmeticException if this isn't a proper Java int 432 case NUMBER: 433 434 // REMEMBER: The primary reason for this class is that MEANINGFUL ERROR MESSAGES 435 // make Json-Binding a lot easer... "JsonArithmeticException" has just 436 // about everything that you need to know when debugging this stuff 437 438 try 439 { return jsonTypeToJavaType.apply((JsonNumber) jv); } 440 441 catch (ArithmeticException ae) 442 { 443 throw new JsonArithmeticObjException 444 (ae, jo, propertyName, NUMBER, jv, primitiveClass); 445 } 446 447 // The JsonObject property does not contain a JsonNumber. 448 default: throw new JsonTypeObjException 449 (jo, propertyName, NUMBER, jv, primitiveClass); 450 } 451 } 452 453 /** 454 * This is an internal helper method for retrieving a property from a {@link JsonObject}, 455 * and converting it to one of the standard <B STYLE='color: red;'>Java Types</B>. 456 * 457 * @param <T> <EMBED CLASS='external-html' DATA-FILE-ID=JR_GET_T> 458 * @param jo Any instance of {@link JsonObject} 459 * @param propertyName Any property name contained by {@code 'jo'} 460 * @param isOptional Indicates whether {@code 'propertyName'} may be missing from {@code 'jo'} 461 * @param jsonTypeToJavaType <EMBED CLASS='external-html' DATA-FILE-ID=JR_GET_JTTJT> 462 * 463 * @return The converted number, as an instance Generic-Parameter {@code 'T'} 464 * 465 * @throws JsonPropMissingException If the property is missing, and {@code 'isOptional'} 466 * is {@code FALSE}. 467 * @throws JsonTypeObjException <EMBED CLASS='external-html' DATA-FILE-ID=JR_GET_JTAEX> 468 * @throws JsonArithmeticObjException If there any arithmetic problems during the conversion 469 * 470 * @see ReadBoxedJSON#getInteger(JsonObject, String, boolean) 471 * @see ReadBoxedJSON#getLong(JsonObject, String, boolean) 472 * @see ReadBoxedJSON#getShort(JsonObject, String, boolean) 473 * @see ReadBoxedJSON#getByte(JsonObject, String, boolean) 474 * @see ReadBoxedJSON#getDouble(JsonObject, String, boolean) 475 * @see ReadBoxedJSON#getFloat(JsonObject, String, boolean) 476 */ 477 protected static <T extends java.lang.Number> T GET( 478 JsonObject jo, String propertyName, boolean isOptional, 479 Function<JsonNumber, T> jsonTypeToJavaType, Class<T> returnClass 480 ) 481 { 482 // Here, a 'get' request was made for a property that isn't actually listed among the 483 // properties in the provided JsonObject. If 'isOptional' return null, otherwise throw 484 485 if (! jo.containsKey(propertyName)) 486 { 487 if (isOptional) return null; 488 489 throw new JsonPropMissingException 490 (jo, propertyName, NUMBER, returnClass); 491 } 492 493 JsonValue jv = jo.get(propertyName); 494 495 switch (jv.getValueType()) 496 { 497 // This method allows for null-returns. If Json-Null, return Java-Null. 498 case NULL: return null; 499 500 // This will throw ArithmeticException if this isn't a proper Java int 501 case NUMBER: 502 503 // REMEMBER: The primary reason for this class is that MEANINGFUL ERROR MESSAGES 504 // make Json-Binding a lot easer... "JsonArithmeticException" has just 505 // about everything that you need to know when debugging this stuff 506 507 try 508 { return jsonTypeToJavaType.apply((JsonNumber) jv); } 509 510 catch (ArithmeticException ae) 511 { 512 throw new JsonArithmeticObjException 513 (ae, jo, propertyName, NUMBER, jv, returnClass); 514 } 515 516 // The JsonObject property does not contain a JsonNumber. 517 default: throw new JsonTypeObjException 518 (jo, propertyName, NUMBER, jv, returnClass); 519 } 520 } 521 522 523 // ******************************************************************************************** 524 // ******************************************************************************************** 525 // FLAG-CHECKER METHODS another section of "Helpers for the Helpers ..." 526 // ******************************************************************************************** 527 // ******************************************************************************************** 528 529 530 /** 531 * Flag Checker for {@code IndexOutOfBoundsException}. 532 * 533 * <BR /><BR />Checks whether the relevant flags were set in the users {@code FLAGS} parameter, 534 * and either returns the appropriate value accordingly, or throws 535 * {@code IndexOutOfBoundsException}. 536 * 537 * <EMBED CLASS='external-html' DATA-FILE-ID=FLAG_PRECEDENCE> 538 * 539 * @param <T> If requested, the default-value is returned, and this is its type. 540 * 541 * @return Can return either the user-provided default-value, or null depending on whether a 542 * match was found in the user's request settings ({@code 'FLAGS'}). 543 * 544 * @throws IndexOutOfBoundsException If no flag was set specifying one of the two return-value 545 * options. 546 * 547 * @see JFlag#RETURN_NULL_ON_IOB 548 * @see JFlag#RETURN_DEFVAL_ON_IOB 549 * @see JFlag#RETURN_NULL_ON_ANY_ALL 550 * @see JFlag#RETURN_DEFVAL_ON_ANY_ALL 551 */ 552 protected static <T> T IOOBEX(JsonArray ja, int index, T defaultValue, int FLAGS) 553 { 554 if ((FLAGS & RETURN_NULL_ON_IOB) != 0) return null; 555 if ((FLAGS & RETURN_DEFVAL_ON_IOB) != 0) return defaultValue; 556 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 557 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 558 559 ja.get(index); // Throws an IndexOutOfBoundsException 560 561 // If you have reached this statment, this method was not applied properly 562 throw new Torello.Java.UnreachableError(); 563 } 564 565 /** 566 * Flag Checker for {@link JsonPropMissingException} 567 * 568 * <BR /><BR />Checks whether the relevant flags were set in the users {@code FLAGS} parameter, 569 * and either returns the appropriate value accordingly, or throws 570 * {@code JsonPropMissingException}. 571 * 572 * <EMBED CLASS='external-html' DATA-FILE-ID=FLAG_PRECEDENCE> 573 * 574 * @param <T> If requested, the default-value is returned, and this is its type. 575 * 576 * @return Can return either the user-provided default-value, or null depending on whether a 577 * match was found in the user's request settings ({@code 'FLAGS'}). 578 * 579 * @throws JsonPropMissingException If no flag was set specifying one of the two return-value 580 * options. 581 * 582 * @see JFlag#RETURN_NULL_ON_MISSING 583 * @see JFlag#RETURN_DEFVAL_ON_MISSING 584 * @see JFlag#RETURN_NULL_ON_ANY_ALL 585 * @see JFlag#RETURN_DEFVAL_ON_ANY_ALL 586 */ 587 protected static <T> T JPMEX( 588 JsonObject jo, String propertyName, T defaultValue, int FLAGS, 589 JsonValue.ValueType expectedType, Class<T> returnClass 590 ) 591 { 592 if ((FLAGS & RETURN_NULL_ON_MISSING) != 0) return null; 593 if ((FLAGS & RETURN_DEFVAL_ON_MISSING) != 0) return defaultValue; 594 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 595 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 596 597 throw new JsonPropMissingException(jo, propertyName, expectedType, returnClass); 598 } 599 600 /** 601 * Flag Checker for {@link JsonNullArrException} 602 * 603 * <BR /><BR />Checks whether the relevant flags were set in the users {@code FLAGS} parameter, 604 * and either returns the appropriate value accordingly, or throws 605 * {@code JsonNullArrException}. 606 * 607 * <EMBED CLASS='external-html' DATA-FILE-ID=FLAG_PRECEDENCE> 608 * 609 * @param <T> If requested, the default-value is returned, and this is its type. 610 * 611 * @return Can return either the user-provided default-value, or null depending on whether a 612 * match was found in the user's request settings ({@code 'FLAGS'}). 613 * 614 * @throws JsonNullArrException If no flag was set specifying one of the two return-value 615 * options. 616 * 617 * @see JFlag#RETURN_NULL_ON_NULL 618 * @see JFlag#RETURN_DEFVAL_ON_NULL 619 * @see JFlag#RETURN_NULL_ON_ANY_ALL 620 * @see JFlag#RETURN_DEFVAL_ON_ANY_ALL 621 */ 622 protected static <T> T JNAEX( 623 JsonArray ja, int index, T defaultValue, int FLAGS, JsonValue.ValueType expectedType, 624 Class<T> returnClass 625 ) 626 { 627 if ((FLAGS & RETURN_NULL_ON_NULL) != 0) return null; 628 if ((FLAGS & RETURN_DEFVAL_ON_NULL) != 0) return defaultValue; 629 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 630 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 631 632 throw new JsonNullArrException(ja, index, expectedType, returnClass); 633 } 634 635 /** 636 * Flag Checker for {@link JsonNullObjException} 637 * 638 * <BR /><BR />Checks whether the relevant flags were set in the users {@code FLAGS} parameter, 639 * and either returns the appropriate value accordingly, or throws 640 * {@code JsonNullObjException}. 641 * 642 * <EMBED CLASS='external-html' DATA-FILE-ID=FLAG_PRECEDENCE> 643 * 644 * @param <T> If requested, the default-value is returned, and this is its type. 645 * 646 * @return Can return either the user-provided default-value, or null depending on whether a 647 * match was found in the user's request settings ({@code 'FLAGS'}). 648 * 649 * @throws JsonNullObjException If no flag was set specifying one of the two return-value 650 * options. 651 * 652 * @see JFlag#RETURN_NULL_ON_NULL 653 * @see JFlag#RETURN_DEFVAL_ON_NULL 654 * @see JFlag#RETURN_NULL_ON_ANY_ALL 655 * @see JFlag#RETURN_DEFVAL_ON_ANY_ALL 656 */ 657 protected static <T> T JNOEX( 658 JsonObject jo, String propertyName, T defaultValue, int FLAGS, 659 JsonValue.ValueType expectedType, Class<T> returnClass 660 ) 661 { 662 if ((FLAGS & RETURN_NULL_ON_NULL) != 0) return null; 663 if ((FLAGS & RETURN_DEFVAL_ON_NULL) != 0) return defaultValue; 664 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 665 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 666 667 throw new JsonNullObjException(jo, propertyName, expectedType, returnClass); 668 } 669 670 /** 671 * Flag Checker for {@link JsonTypeArrException} 672 * 673 * <BR /><BR />Checks whether the relevant flags were set in the users {@code FLAGS} parameter, 674 * and either returns the appropriate value accordingly, or throws 675 * {@code JsonTypeArrException}. 676 * 677 * <EMBED CLASS='external-html' DATA-FILE-ID=FLAG_PRECEDENCE> 678 * 679 * @param <T> If requested, the default-value is returned, and this is its type. 680 * 681 * @return Can return either the user-provided default-value, or null depending on whether a 682 * match was found in the user's request settings ({@code 'FLAGS'}). 683 * 684 * @throws JsonTypeArrException If no flag was set specifying one of the two return-value 685 * options. 686 * 687 * @see JFlag#RETURN_NULL_ON_WRONG_JSONTYPE 688 * @see JFlag#RETURN_DEFVAL_ON_WRONG_JSONTYPE 689 * @see JFlag#RETURN_NULL_ON_ANY_ALL 690 * @see JFlag#RETURN_DEFVAL_ON_ANY_ALL 691 */ 692 protected static <T> T JTAEX( 693 JsonArray ja, int index, T defaultValue, int FLAGS, JsonValue.ValueType expectedType, 694 JsonValue retrievedValue, Class<T> returnClass 695 ) 696 { 697 if ((FLAGS & RETURN_NULL_ON_WRONG_JSONTYPE) != 0) return null; 698 if ((FLAGS & RETURN_DEFVAL_ON_WRONG_JSONTYPE) != 0) return defaultValue; 699 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 700 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 701 702 throw new JsonTypeArrException(ja, index, expectedType, retrievedValue, returnClass); 703 } 704 705 /** 706 * Flag Checker for {@link JsonTypeObjException} 707 * 708 * <BR /><BR />Checks whether the relevant flags were set in the users {@code FLAGS} parameter, 709 * and either returns the appropriate value accordingly, or throws 710 * {@code JsonNullObjException}. 711 * 712 * <EMBED CLASS='external-html' DATA-FILE-ID=FLAG_PRECEDENCE> 713 * 714 * @param <T> If requested, the default-value is returned, and this is its type. 715 * 716 * @return Can return either the user-provided default-value, or null depending on whether a 717 * match was found in the user's request settings ({@code 'FLAGS'}). 718 * 719 * @throws JsonNullObjException If no flag was set specifying one of the two return-value 720 * options. 721 * 722 * @see JFlag#RETURN_NULL_ON_WRONG_JSONTYPE 723 * @see JFlag#RETURN_DEFVAL_ON_WRONG_JSONTYPE 724 * @see JFlag#RETURN_NULL_ON_ANY_ALL 725 * @see JFlag#RETURN_DEFVAL_ON_ANY_ALL 726 */ 727 protected static <T> T JTOEX( 728 JsonObject jo, String propertyName, T defaultValue, int FLAGS, 729 JsonValue.ValueType expectedType, JsonValue retrievedValue, Class<T> returnClass 730 ) 731 { 732 if ((FLAGS & RETURN_NULL_ON_WRONG_JSONTYPE) != 0) return null; 733 if ((FLAGS & RETURN_DEFVAL_ON_WRONG_JSONTYPE) != 0) return defaultValue; 734 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 735 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 736 737 throw new JsonTypeObjException 738 (jo, propertyName, expectedType, retrievedValue, returnClass); 739 } 740 741 /** 742 * Flag Checker for {@link JsonStrParseArrException} 743 * 744 * <BR /><BR />Checks whether the relevant flags were set in the users {@code FLAGS} parameter, 745 * and either returns the appropriate value accordingly, or throws 746 * {@code JsonStrParseArrException}. 747 * 748 * <EMBED CLASS='external-html' DATA-FILE-ID=FLAG_PRECEDENCE> 749 * 750 * @param <T> If requested, the default-value is returned, and this is its type. 751 * 752 * @return Can return either the user-provided default-value, or null depending on whether a 753 * match was found in the user's request settings ({@code 'FLAGS'}). 754 * 755 * @throws JsonStrParseArrException If no flag was set specifying one of the two return-value 756 * options. 757 * 758 * @see JFlag#RETURN_NULL_ON_SPEX 759 * @see JFlag#RETURN_DEFVAL_ON_SPEX 760 * @see JFlag#RETURN_NULL_ON_ANY_ALL 761 * @see JFlag#RETURN_DEFVAL_ON_ANY_ALL 762 */ 763 protected static <T> T JSPAEX( 764 Exception e, JsonArray ja, int index, T defaultValue, int FLAGS, 765 JsonValue retrievedValue, Class<T> returnClass 766 ) 767 { 768 if ((FLAGS & RETURN_NULL_ON_SPEX) != 0) return null; 769 if ((FLAGS & RETURN_DEFVAL_ON_SPEX) != 0) return defaultValue; 770 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 771 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 772 773 throw new JsonStrParseArrException(e, ja, index, retrievedValue, returnClass); 774 } 775 776 /** 777 * Flag Checker for {@link JsonStrParseObjException} 778 * 779 * <BR /><BR />Checks whether the relevant flags were set in the users {@code FLAGS} parameter, 780 * and either returns the appropriate value accordingly, or throws 781 * {@code JsonStrParseObjException}. 782 * 783 * <EMBED CLASS='external-html' DATA-FILE-ID=FLAG_PRECEDENCE> 784 * 785 * @param <T> If requested, the default-value is returned, and this is its type. 786 * 787 * @return Can return either the user-provided default-value, or null depending on whether a 788 * match was found in the user's request settings ({@code 'FLAGS'}). 789 * 790 * @throws JsonStrParseObjException If no flag was set specifying one of the two return-value 791 * options. 792 * 793 * @see JFlag#RETURN_NULL_ON_SPEX 794 * @see JFlag#RETURN_DEFVAL_ON_SPEX 795 * @see JFlag#RETURN_NULL_ON_ANY_ALL 796 * @see JFlag#RETURN_DEFVAL_ON_ANY_ALL 797 */ 798 protected static <T> T JSPOEX( 799 Exception e, JsonObject jo, String propertyName, T defaultValue, int FLAGS, 800 JsonValue retrievedValue, Class<T> returnClass 801 ) 802 { 803 if ((FLAGS & RETURN_NULL_ON_SPEX) != 0) return null; 804 if ((FLAGS & RETURN_DEFVAL_ON_SPEX) != 0) return defaultValue; 805 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 806 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 807 808 throw new JsonStrParseObjException(e, jo, propertyName, retrievedValue, returnClass); 809 } 810 811 812 // ******************************************************************************************** 813 // ******************************************************************************************** 814 // GET: USES-FLAG METHODS 815 // ******************************************************************************************** 816 // ******************************************************************************************** 817 818 819 /** 820 * This is an internal helper method for retrieving an element from a {@link JsonArray}, 821 * and converting it to a <B STYLE='color: red;'>Java Type</B>. 822 * <EMBED CLASS=defs DATA-TYPE=number DATA-JTYPE=JsonNumber> 823 * @param ja Any instance of {@link JsonArray} 824 * @param index The array index containing the element to retrieve. 825 * @param FLAGS The return-value / exception-throw flag constants defined in {@link JFlag} 826 * @param defaultValue This is the 'Default Value' returned by this method, if there are any 827 * problems converting or extracting the specified number, and the appropriate flags are set. 828 * 829 * @return On success, this method returns the converted number. 830 * 831 * @throws IndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=JRF_IOOBEX> 832 * @throws JsonArithmeticArrException <EMBED CLASS='external-html' DATA-FILE-ID=JRF_JAEX> 833 * @throws JsonNullArrException <EMBED CLASS='external-html' DATA-FILE-ID=JRF_JNAEX> 834 * @throws JsonTypeArrException <EMBED CLASS='external-html' DATA-FILE-ID=JRF_JTAEX> 835 * 836 * @see ReadBoxedJSON#getInteger(JsonArray, int, int, int) 837 * @see ReadBoxedJSON#getLong(JsonArray, int, int, long) 838 * @see ReadBoxedJSON#getShort(JsonArray, int, int, short) 839 * @see ReadBoxedJSON#getByte(JsonArray, int, int, byte) 840 * @see ReadBoxedJSON#getDouble(JsonArray, int, int, double) 841 * @see ReadBoxedJSON#getFloat(JsonArray, int, int, float) 842 * @see ReadNumberJSON#get(JsonArray, int, int, Number) 843 */ 844 protected static <T extends java.lang.Number> T GET( 845 JsonArray ja, int index, 846 int FLAGS, T defaultValue, 847 Class<T> returnClass, 848 Function<JsonNumber, T> jsonTypeToJavaType, 849 Function<JsonNumber, T> typeToType2 850 ) 851 { 852 // When TRUE, the index provided turned out to be outside of the bounds of the array. The 853 // IndexOutOfBounds "handler" (the method called here) will check the FLAGS, and: 854 // 855 // 1) return the defaultValue (if Requested by 'FLAGS' for IOOBEX) 856 // 2) return null (if Requested by 'FLAGS' for IOOBEX) 857 // 3) throw IndexOutOfBoundsException 858 // 859 // NOTE: It is probably a "little less efficient" to turn this into a method call, 860 // since there are all these parameters that have to be passed, but this is 861 // trading "readability" (less head-aches) in exchange for efficiency. 862 // 863 // This point applies to all of the "Exception Flag Handlers" used here 864 865 if (index >= ja.size()) return IOOBEX(ja, index, defaultValue, FLAGS); 866 867 JsonValue jv = ja.get(index); 868 869 switch (jv.getValueType()) 870 { 871 // When a 'NULL' (Json-Null) JsonValue is present, the JsonNullArrException 'handler' 872 // will do one of the following: 873 // 874 // 1) return the defaultValue (if Requested by 'FLAGS' for JNAEX) 875 // 2) return null (if Requested by 'FLAGS' for JNAEX) 876 // 3) throw JsonNullArrException 877 878 case NULL: return JNAEX(ja, index, defaultValue, FLAGS, NUMBER, returnClass); 879 880 case NUMBER: 881 882 // Temp Variable, Used Twice (Just a Cast) 883 JsonNumber n = (JsonNumber) jv; 884 885 try 886 { return jsonTypeToJavaType.apply(n); } 887 888 // Because 889 // 890 // 1) A method for this code would only be invoked here, and... 891 // 2) And because there would be 9 parameters to pass, 892 // 3) the 'inline' version of "Flag Handler" is left here! 893 // 894 // NOTE: All four "JsonArithmetic Arr/Obj Exception" exception throws 895 // are different for each of the 4 methods where they are used. 896 897 catch (ArithmeticException ae) 898 { 899 if ((FLAGS & RETURN_NULL_ON_AEX) != 0) return null; 900 if ((FLAGS & RETURN_DEFVAL_ON_AEX) != 0) return defaultValue; 901 if ((FLAGS & RETURN_JAPPROX_ON_AEX) != 0) return typeToType2.apply(n); 902 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 903 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 904 905 throw new JsonArithmeticArrException 906 (ae, ja, index, NUMBER, jv, returnClass); 907 } 908 909 // The JsonValue at the specified array-index does not contain an JsonNumber. 910 // The "JsonTypeArrException Handler" will do one of these: 911 // 912 // 1) return the defaultValue (if Requested by 'FLAGS' for JTAEX) 913 // 2) return null (if Requested by 'FLAGS' for JTAEX) 914 // 3) throw JsonTypeArrException 915 916 default: return JTAEX(ja, index, defaultValue, FLAGS, NUMBER, jv, returnClass); 917 } 918 } 919 920 /** 921 * This is an internal helper method for retrieving a property from a {@link JsonObject}, 922 * and converting it to a <B STYLE='color: red;'>Java Type</B>. 923 * <EMBED CLASS=defs DATA-TYPE=number DATA-JTYPE=JsonNumber> 924 * 925 * @param jo Any instance of {@link JsonObject} 926 * @param propertyName The name of the property in {@code 'jo'} to retrieve. 927 * @param FLAGS The return-value / exception-throw flag constants defined in {@link JFlag} 928 * @param defaultValue This is the 'Default Value' returned by this method, if there are any 929 * problems converting or extracting the specified number, and the appropriate flags are set 930 * 931 * @return On success, this method returns the converted number 932 * 933 * @throws JsonPropMissingException <EMBED CLASS='external-html' DATA-FILE-ID=JRF_JPMEX> 934 * @throws JsonArithmeticObjException <EMBED CLASS='external-html' DATA-FILE-ID=JRF_JAEX> 935 * @throws JsonNullObjException <EMBED CLASS='external-html' DATA-FILE-ID=JRF_JNOEX> 936 * @throws JsonTypeObjException <EMBED CLASS='external-html' DATA-FILE-ID=JRF_JTOEX> 937 * 938 * @see ReadBoxedJSON#getInteger(JsonObject, String, int, int) 939 * @see ReadBoxedJSON#getLong(JsonObject, String, int, long) 940 * @see ReadBoxedJSON#getShort(JsonObject, String, int, short) 941 * @see ReadBoxedJSON#getByte(JsonObject, String, int, byte) 942 * @see ReadBoxedJSON#getDouble(JsonObject, String, int, double) 943 * @see ReadBoxedJSON#getFloat(JsonObject, String, int, float) 944 * @see ReadNumberJSON#get(JsonObject, String, int, Number) 945 */ 946 protected static <T extends java.lang.Number> T GET( 947 JsonObject jo, String propertyName, 948 int FLAGS, T defaultValue, 949 Class<T> returnClass, 950 Function<JsonNumber, T> jsonTypeToJavaType, 951 Function<JsonNumber, T> typeToType2 952 ) 953 { 954 JsonValue jv = jo.get(propertyName); 955 956 // When TRUE, the user-specified 'property' (named by 'propertyName') isn't actually one 957 // of the listed properties inside the JsonObject. The JsonPropMissingException "handler" 958 // (the method called here) will check the FLAGS, and: 959 // 960 // 1) return the defaultValue (if Requested by 'FLAGS' for JPMEX) 961 // 2) return null (if Requested by 'FLAGS' for JPMEX) 962 // 3) throw JsonPropMissingException 963 // 964 // NOTE: It is probably a "little less efficient" to turn this into a method call, 965 // since there are all these parameters that have to be passed, but this is 966 // trading "readability" (less head-aches) in exchange for efficiency. 967 // 968 // This point applies to all of the "Exception Flag Handlers" used here 969 970 if (jv == null) return JPMEX(jo, propertyName, defaultValue, FLAGS, NUMBER, returnClass); 971 972 switch (jv.getValueType()) 973 { 974 // When a 'NULL' (Json-Null) JsonValue is present, the JsonNullObjException 'handler' 975 // will do one of the following: 976 // 977 // 1) return the defaultValue (if Requested by 'FLAGS' for JNOEX) 978 // 2) return null (if Requested by 'FLAGS' for JNOEX) 979 // 3) throw JsonNullArrException 980 981 case NULL: return JNOEX(jo, propertyName, defaultValue, FLAGS, NUMBER, returnClass); 982 983 case NUMBER: 984 985 // Temp Variable, Used Twice (Just a Cast) 986 JsonNumber n = (JsonNumber) jv; 987 988 try 989 { return jsonTypeToJavaType.apply(n); } 990 991 // Because 992 // 993 // 1) A method for this code would only be invoked here, and... 994 // 2) And because there would be 9 parameters to pass, 995 // 3) the 'inline' version of "Flag Handler" is left here! 996 // 997 // NOTE: All four "JsonArithmetic Arr/Obj Exception" exception throws 998 // are different for each of the 4 methods where they are used. 999 1000 catch (ArithmeticException ae) 1001 { 1002 if ((FLAGS & RETURN_NULL_ON_AEX) != 0) return null; 1003 if ((FLAGS & RETURN_DEFVAL_ON_AEX) != 0) return defaultValue; 1004 if ((FLAGS & RETURN_JAPPROX_ON_AEX) != 0) return typeToType2.apply(n); 1005 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 1006 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 1007 1008 throw new JsonArithmeticObjException 1009 (ae, jo, propertyName, NUMBER, jv, returnClass); 1010 } 1011 1012 // The JsonValue of 'propertyName' does not contain an JsonNumber. 1013 // The "JsonTypeObjException Handler" will do one of these: 1014 // 1015 // 1) return the defaultValue (if Requested by 'FLAGS' for JTOEX) 1016 // 2) return null (if Requested by 'FLAGS' for JTOEX) 1017 // 3) throw JsonTypeObjException 1018 1019 default: return JTOEX(jo, propertyName, defaultValue, FLAGS, NUMBER, jv, returnClass); 1020 } 1021 } 1022 1023 1024 // ******************************************************************************************** 1025 // ******************************************************************************************** 1026 // HELPER PARSE - JsonString Inputs (also uses flags) 1027 // ******************************************************************************************** 1028 // ******************************************************************************************** 1029 1030 1031 /** 1032 * Retrieve a {@link JsonArray} element containing a {@link JsonString}, and transform it to 1033 * a <B STYLE='color: red'>Java Type</B>, with either a user-provided parser, or the standard 1034 * java parser for that class (passed as a parameter). 1035 * 1036 * @param <T> The type of the returned value 1037 * @param ja Any instance of {@link JsonArray} 1038 * @param index array-index containing the {@link JsonString} to retrieve. 1039 * @param FLAGS The return-value / exception-throw flag constants defined in {@link JFlag} 1040 * @param defaultValue User-provided default-value, only returned if flags are set. 1041 * @param parser A valid {@code String -> 'T'} parser. This parameter may be null. 1042 * @param defaultParser1 Default {@code String -> 'T'} parser. 1043 * @param defaultParser2 {@code String -> 'T'} parser, that will round on Arithmetic Exceptions 1044 * 1045 * @return On success, this method returns the converted type. 1046 * 1047 * @throws JsonPropMissingException {@code 'jo'} doesn't have {@code 'propertyName'}, unless 1048 * flags are set. 1049 * @throws JsonArithmeticArrException after parse, conversion fails, and flags aren't set 1050 * @throws JsonStrParseArrException parser-failure unless flags are set 1051 * @throws JsonNullArrException property contains null, unless flags are set 1052 * @throws JsonTypeArrException property doesn't contain {@code JsonString}, unless flags are 1053 * set. 1054 * 1055 * @see ReadBoxedJSON#parseInteger(JsonArray, int, int, int, Function) 1056 * @see ReadBoxedJSON#parseLong(JsonArray, int, int, long, Function) 1057 * @see ReadBoxedJSON#parseShort(JsonArray, int, int, short, Function) 1058 * @see ReadBoxedJSON#parseByte(JsonArray, int, int, byte, Function) 1059 * @see ReadBoxedJSON#parseDouble(JsonArray, int, int, double, Function) 1060 * @see ReadBoxedJSON#parseFloat(JsonArray, int, int, float, Function) 1061 * @see ReadNumberJSON#parse(JsonArray, int, int, Number, Function) 1062 */ 1063 protected static <T extends Number> T PARSE( 1064 JsonArray ja, int index, int FLAGS, T defaultValue, Class<T> returnClass, 1065 Function<String, T> parser, 1066 Function<BigDecimal, T> defaultParser1, 1067 Function<BigDecimal, T> defaultParser2 1068 ) 1069 { 1070 // When TRUE, the index provided turned out to be outside of the bounds of the array. The 1071 // IndexOutOfBounds "handler" (the method called here) will check the FLAGS, and: 1072 // 1073 // 1) return the defaultValue (if Requested by 'FLAGS' for IOOBEX) 1074 // 2) return null (if Requested by 'FLAGS' for IOOBEX) 1075 // 3) throw IndexOutOfBoundsException 1076 // 1077 // NOTE: It is probably a "little less efficient" to turn this into a method call, 1078 // since there are all these parameters that have to be passed, but this is 1079 // trading "readability" (less head-aches) in exchange for efficiency. 1080 // 1081 // This point applies to all of the "Exception Flag Handlers" used here 1082 1083 if (index >= ja.size()) return IOOBEX(ja, index, defaultValue, FLAGS); 1084 1085 JsonValue jv = ja.get(index); 1086 1087 switch (jv.getValueType()) 1088 { 1089 // When a 'NULL' (Json-Null) JsonValue is present, the JsonNullArrException 'handler' 1090 // will do one of the following: 1091 // 1092 // 1) return the defaultValue (if Requested by 'FLAGS' for JNAEX) 1093 // 2) return null (if Requested by 'FLAGS' for JNAEX) 1094 // 3) throw JsonNullArrException 1095 1096 case NULL: return JNAEX(ja, index, defaultValue, FLAGS, STRING, returnClass); 1097 1098 case STRING: 1099 1100 String s = ((JsonString) jv).getString(); 1101 1102 // NOTE: This isn't actually an "Exception Case", and if the user hasn't made 1103 // a request, the empty-string is passed to whatever parser is configured 1104 1105 if (s.length() == 0) 1106 { 1107 if ((FLAGS & RETURN_NULL_ON_0LEN_STR) != 0) return null; 1108 if ((FLAGS & RETURN_DEFVAL_ON_0LEN_STR) != 0) return defaultValue; 1109 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 1110 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 1111 } 1112 1113 // Temp Variable, used in order not to invoke the BigDecimal contructor twice 1114 BigDecimal bd = null; 1115 1116 try 1117 { 1118 return (parser != null) 1119 ? parser.apply(s) 1120 : defaultParser1.apply(bd = new BigDecimal(s.trim())); 1121 1122 // NOTE: 'bd' will not be null if "ArithmeticException" is thrown... 1123 // new BigDecimal throws "NumberFormatException" is thrown 1124 // parser.applly can throw ArithmeticException 1125 } 1126 1127 // Because 1128 // 1129 // 1) A method for this code would only be invoked here, and... 1130 // 2) And because there would be 9 parameters to pass, 1131 // 3) the 'inline' version of "Flag Handler" is left here! 1132 // 1133 // NOTE: All four "JsonArithmetic Arr/Obj Exception" exception throws 1134 // are different for each of the 4 methods where they are used. 1135 1136 catch (ArithmeticException ae) 1137 { 1138 if ((FLAGS & RETURN_NULL_ON_AEX) != 0) return null; 1139 if ((FLAGS & RETURN_DEFVAL_ON_AEX) != 0) return defaultValue; 1140 if ((FLAGS & RETURN_JAPPROX_ON_AEX) != 0) return defaultParser2.apply(bd); 1141 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 1142 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 1143 1144 throw new JsonArithmeticArrException(ae, ja, index, STRING, jv, returnClass); 1145 } 1146 1147 // HANDLER STRIKES AGAIN! - but this time for "JsonStrParseArrException" 1148 // RETURNS: null, or defaultValue, (otherwise throws JsonStrParseArrException) 1149 1150 catch (Exception e) 1151 { return JSPAEX(e, ja, index, defaultValue, FLAGS, jv, returnClass); } 1152 1153 // The JsonValue at the specified array-index does not contain an JsonString. 1154 // The "JsonTypeArrException Handler" will do one of these: 1155 // 1156 // 1) return the defaultValue (if Requested by 'FLAGS' for JTAEX) 1157 // 2) return null (if Requested by 'FLAGS' for JTAEX) 1158 // 3) throw JsonTypeArrException 1159 1160 default: return JTAEX(ja, index, defaultValue, FLAGS, STRING, jv, returnClass); 1161 } 1162 } 1163 1164 /** 1165 * Retrieve a {@link JsonObject} property containing a {@link JsonString}, and transform it to 1166 * a <B STYLE='color: red'>Java Type</B>, with either a user-provided parser, or the standard 1167 * java parser for that class (passed as a parameter). 1168 * 1169 * @param <T> The type of the returned value. 1170 * @param jo Any instance of {@link JsonObject} 1171 * @param propertyName propertyName containing the {@link JsonString} to retrieve. 1172 * @param FLAGS The return-value / exception-throw flag constants defined in {@link JFlag} 1173 * @param defaultValue User-provided default-value, only returned if flags are set. 1174 * @param parser A valid {@code String -> 'T'} parser. This parameter may be null. 1175 * @param defaultParser1 Default {@code String -> 'T'} parser. 1176 * @param defaultParser2 {@code String -> 'T'} parser, that will round on Arithmetic Exceptions 1177 * 1178 * @return On success, this method returns the converted type instance. 1179 * 1180 * @throws JsonPropMissingException {@code 'jo'} doesn't have {@code 'propertyName'}, unless 1181 * flags are set. 1182 * @throws JsonArithmeticObjException after parse, conversion fails, and flags aren't set 1183 * @throws JsonStrParseObjException parser-failure unless flags are set 1184 * @throws JsonNullObjException property contains null, unless flags are set 1185 * @throws JsonTypeObjException property doesn't contain {@code JsonString}, unless flags are 1186 * set. 1187 * 1188 * @see ReadBoxedJSON#parseInteger(JsonObject, String, int, int, Function) 1189 * @see ReadBoxedJSON#parseLong(JsonObject, String, int, long, Function) 1190 * @see ReadBoxedJSON#parseShort(JsonObject, String, int, short, Function) 1191 * @see ReadBoxedJSON#parseByte(JsonObject, String, int, byte, Function) 1192 * @see ReadBoxedJSON#parseDouble(JsonObject, String, int, double, Function) 1193 * @see ReadBoxedJSON#parseFloat(JsonObject, String, int, float, Function) 1194 * @see ReadNumberJSON#parse(JsonObject, String, int, Number, Function) 1195 */ 1196 protected static <T extends Number> T PARSE( 1197 JsonObject jo, String propertyName, int FLAGS, T defaultValue, Class<T> returnClass, 1198 Function<String, T> parser, 1199 Function<BigDecimal, T> defaultParser1, 1200 Function<BigDecimal, T> defaultParser2 1201 ) 1202 { 1203 JsonValue jv = jo.get(propertyName); 1204 1205 // When TRUE, the user-specified 'property' (named by 'propertyName') isn't actually one 1206 // of the listed properties inside the JsonObject. The JsonPropMissingException "handler" 1207 // (the method called here) will check the FLAGS, and: 1208 // 1209 // 1) return the defaultValue (if Requested by 'FLAGS' for JPMEX) 1210 // 2) return null (if Requested by 'FLAGS' for JPMEX) 1211 // 3) throw JsonPropMissingException 1212 // 1213 // NOTE: It is probably a "little less efficient" to turn this into a method call, 1214 // since there are all these parameters that have to be passed, but this is 1215 // trading "readability" (less head-aches) in exchange for efficiency. 1216 // 1217 // This point applies to all of the "Exception Flag Handlers" used here 1218 1219 if (jv == null) return JPMEX(jo, propertyName, defaultValue, FLAGS, STRING, returnClass); 1220 1221 switch (jv.getValueType()) 1222 { 1223 // When a 'NULL' (Json-Null) JsonValue is present, the JsonNullObjException 'handler' 1224 // will do one of the following: 1225 // 1226 // 1) return the defaultValue (if Requested by 'FLAGS' for JNOEX) 1227 // 2) return null (if Requested by 'FLAGS' for JNOEX) 1228 // 3) throw JsonNullArrException 1229 1230 case NULL: return JNOEX(jo, propertyName, defaultValue, FLAGS, STRING, returnClass); 1231 1232 case STRING: 1233 1234 String s = ((JsonString) jv).getString(); 1235 1236 // NOTE: This isn't actually an "Exception Case", and if the user hasn't made 1237 // a request, the empty-string is passed to whatever parser is configured 1238 1239 if (s.length() == 0) 1240 { 1241 if ((FLAGS & RETURN_NULL_ON_0LEN_STR) != 0) return null; 1242 if ((FLAGS & RETURN_DEFVAL_ON_0LEN_STR) != 0) return defaultValue; 1243 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 1244 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 1245 } 1246 1247 // Temp Variable, used in order not to invoke the BigDecimal contructor twice 1248 BigDecimal bd = null; 1249 1250 try 1251 { 1252 return (parser != null) 1253 ? parser.apply(s) 1254 : defaultParser1.apply(bd = new BigDecimal(s.trim())); 1255 1256 // NOTE: 'bd' will not be null if "ArithmeticException" is thrown... 1257 // new BigDecimal throws "NumberFormatException" is thrown 1258 // parser.applly can throw ArithmeticException 1259 } 1260 1261 // Because 1262 // 1263 // 1) A method for this code would only be invoked here, and... 1264 // 2) And because there would be 9 parameters to pass, 1265 // 3) the 'inline' version of "Flag Handler" is left here! 1266 // 1267 // NOTE: All four "JsonArithmetic Arr/Obj Exception" exception throws 1268 // are different for each of the 4 methods where they are used. 1269 1270 catch (ArithmeticException ae) 1271 { 1272 if ((FLAGS & RETURN_NULL_ON_AEX) != 0) return null; 1273 if ((FLAGS & RETURN_DEFVAL_ON_AEX) != 0) return defaultValue; 1274 if ((FLAGS & RETURN_JAPPROX_ON_AEX) != 0) return defaultParser2.apply(bd); 1275 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 1276 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 1277 1278 throw new JsonArithmeticObjException 1279 (ae, jo, propertyName, STRING, jv, returnClass); 1280 } 1281 1282 // HANDLER STRIKES AGAIN! - but this time for "JsonStrParseObjException" 1283 // RETURNS: null, or defaultValue, (otherwise throws JsonStrParseObjException) 1284 1285 catch (Exception e) 1286 { return JSPOEX(e, jo, propertyName, defaultValue, FLAGS, jv, returnClass); } 1287 1288 // The JsonValue of 'propertyName' does not contain an JsonString. 1289 // The "JsonTypeObjException Handler" will do one of these: 1290 // 1291 // 1) return the defaultValue (if Requested by 'FLAGS' for JTOEX) 1292 // 2) return null (if Requested by 'FLAGS' for JTOEX) 1293 // 3) throw JsonTypeObjException 1294 1295 default: return JTOEX(jo, propertyName, defaultValue, FLAGS, STRING, jv, returnClass); 1296 } 1297 } 1298}