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