001package Torello.JSON; 002 003import javax.json.*; 004 005import java.lang.reflect.Constructor; 006import java.lang.reflect.Modifier; 007 008import java.math.*; 009 010import static javax.json.JsonValue.ValueType.*; 011import static Torello.JSON.JFlag.*; 012 013import java.util.Objects; 014import java.util.function.Function; 015 016/** 017 * Class which provides a series of helper functions for all JSON Type-Binding Reader 018 * Classes. 019 * 020 * <BR /><BR /><DIV CLASS=JDHint> 021 * 100% of the helper-methods that appear here are protected, and cannot be accessed 022 * outside of this package. They are included in the documentation solely for the purposes of 023 * (<I>if you happen to be interested</I>) letting you know how the JSON-Tools work. It is not 024 * intended that programmers would ever need to invoke, directly, any of the methods in this 025 * class! 026 * </DIV> 027 */ 028@Torello.JavaDoc.Annotations.StaticFunctional 029public class RJInternal 030{ 031 private RJInternal() { } 032 033 034 // ******************************************************************************************** 035 // ******************************************************************************************** 036 // "Helpers for the Helpers for the Helpers" 037 // ******************************************************************************************** 038 // ******************************************************************************************** 039 040 041 private static void throwAE_INFINITY 042 (JsonNumber jn, String primTypeName, boolean positiveOrNegative) 043 { 044 throw new ArithmeticException( 045 "When attempting to conver the JsonNumber [" + jn.toString() + "] to a " + 046 primTypeName + " primitive, the number had a magnitude that was too large: " + 047 (positiveOrNegative ? "Positive" : "Negative") + " Infinity was returned." 048 ); 049 } 050 051 private static void throwAE_INFINITY(BigDecimal bd, String primTypeName) 052 { 053 throw new ArithmeticException( 054 "When attempting to conver the JsonNumber [" + bd.toString() + "] to a " + 055 primTypeName + " primitive, the number had a magnitude that was infinite." 056 ); 057 } 058 059 private static void throwAE_PRECISION(BigDecimal bd, String primTypeName) 060 { 061 throw new ArithmeticException( 062 "When attempting to conver the JsonNumber [" + bd.toString() + "] to a " + 063 primTypeName + " primitive, the number had a loss of precision." 064 ); 065 } 066 067 /* 068 * Converts a {@link JsonNumber} into a Java {@code double} 069 * @param jn Any {@link JsonNumber} 070 * @return java {@code double} primitive 071 * @throws ArithmeticException If infinity is returned from the call to 072 * {@code BigDecimal.doubleValue()} 073 * @see JsonNumber#bigDecimalValue() 074 */ 075 protected static double DOUBLE_WITH_CHECK(JsonNumber jn) 076 { return DOUBLE_WITH_CHECK(jn.bigDecimalValue()); } 077 078 /** 079 * Converts a {@code BigDecimal} into a Java {@code double} 080 * @param bd Any {@code BigDecimal} 081 * @return Java {@code double} primitive 082 * @throws ArithmeticException If infinity is returned from the call to 083 * {@code code BigDecimal.doubleValue()} 084 */ 085 protected static double DOUBLE_WITH_CHECK(BigDecimal bd) 086 { 087 double ret = bd.doubleValue(); 088 089 if (Double.isInfinite(ret)) throwAE_INFINITY(bd, "double"); 090 091 if (BigDecimal.valueOf(ret).compareTo(bd) != 0) throwAE_PRECISION(bd, "double"); 092 093 return ret; 094 } 095 096 /** 097 * Converts a {@link JsonNumber} into a Java {@code float} 098 * @param jn Any {@link JsonNumber} 099 * @return java {@code float} primitive 100 * @throws ArithmeticException If infinity is returned from the call to 101 * {@code BigDecimal.floatValue()} 102 * @see JsonNumber#bigDecimalValue() 103 */ 104 protected static float FLOAT_WITH_CHECK(JsonNumber jn) 105 { return FLOAT_WITH_CHECK(jn.bigDecimalValue()); } 106 107 /** 108 * Converts a {@code BigDecimal} into a Java {@code float} 109 * @param bd Any {@code BigDecimal} 110 * @return Java {@code float} primitive 111 * @throws ArithmeticException If infinity is returned from the call to 112 * {@code code BigDecimal.floatValue()} 113 */ 114 protected static float FLOAT_WITH_CHECK(BigDecimal bd) 115 { 116 float ret = bd.floatValue(); 117 118 if (Float.isInfinite(ret)) throwAE_INFINITY(bd, "float"); 119 120 if (BigDecimal.valueOf(ret).compareTo(bd) != 0) throwAE_PRECISION(bd, "float"); 121 122 return ret; 123 } 124 125 /** 126 * Converts a {@code long} into a Java {@code byte} 127 * @param l A long that has been produced by {@link JsonNumber#longValueExact()} 128 * @return A valid {@code byte} primitive 129 * @throws ArithmeticException If the {@code long} doesn't fit into a {@code byte} 130 */ 131 protected static byte BYTE_FROM_LONG(final long l) 132 { 133 if ((l < Byte.MIN_VALUE) || (l > Byte.MAX_VALUE)) 134 throw new ArithmeticException("byte out of range: " + l); 135 136 return (byte) l; 137 } 138 139 /** 140 * Converts a {@code long} into a Java {@code short} 141 * @param l A long that has been produced by {@link JsonNumber#longValueExact()} 142 * @return A valid {@code short} primitive 143 * @throws ArithmeticException If the {@code long} doesn't fit into a {@code short} 144 */ 145 protected static short SHORT_FROM_LONG(final long l) 146 { 147 if ((l < Short.MIN_VALUE) || (l > Short.MAX_VALUE)) 148 throw new ArithmeticException("short out of range: " + l); 149 150 return (short) l; 151 } 152 153 154 // ******************************************************************************************** 155 // ******************************************************************************************** 156 // FLAG-CHECKER METHODS another section of "Helpers for the Helpers ..." 157 // ******************************************************************************************** 158 // ******************************************************************************************** 159 160 161 /** 162 * Flag Checker for {@code IndexOutOfBoundsException}. 163 * 164 * <BR /><BR />Checks whether the relevant flags were set in the users {@code FLAGS} parameter, 165 * and either returns the appropriate value accordingly, or throws 166 * {@code IndexOutOfBoundsException}. 167 * 168 * <EMBED CLASS='external-html' DATA-FILE-ID=FLAG_PRECEDENCE> 169 * 170 * @param <T> If requested, the default-value is returned, and this is its type. 171 * 172 * @return Can return either the user-provided default-value, or null depending on whether a 173 * match was found in the user's request settings ({@code 'FLAGS'}). 174 * 175 * @throws IndexOutOfBoundsException If no flag was set specifying one of the two return-value 176 * options. 177 * 178 * @see JFlag#RETURN_NULL_ON_IOB 179 * @see JFlag#RETURN_DEFVAL_ON_IOB 180 * @see JFlag#RETURN_NULL_ON_ANY_ALL 181 * @see JFlag#RETURN_DEFVAL_ON_ANY_ALL 182 */ 183 protected static <T> T IOOBEX(JsonArray ja, int index, T defaultValue, int FLAGS) 184 { 185 if ((FLAGS & RETURN_NULL_ON_IOB) != 0) return null; 186 if ((FLAGS & RETURN_DEFVAL_ON_IOB) != 0) return defaultValue; 187 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 188 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 189 190 ja.get(index); // Throws an IndexOutOfBoundsException 191 192 // If you have reached this statment, this method was not applied properly 193 throw new Torello.Java.UnreachableError(); 194 } 195 196 /** 197 * Flag Checker for {@link JsonPropMissingException} 198 * 199 * <BR /><BR />Checks whether the relevant flags were set in the users {@code FLAGS} parameter, 200 * and either returns the appropriate value accordingly, or throws 201 * {@code JsonPropMissingException}. 202 * 203 * <EMBED CLASS='external-html' DATA-FILE-ID=FLAG_PRECEDENCE> 204 * 205 * @param <T> If requested, the default-value is returned, and this is its type. 206 * 207 * @return Can return either the user-provided default-value, or null depending on whether a 208 * match was found in the user's request settings ({@code 'FLAGS'}). 209 * 210 * @throws JsonPropMissingException If no flag was set specifying one of the two return-value 211 * options. 212 * 213 * @see JFlag#RETURN_NULL_ON_MISSING 214 * @see JFlag#RETURN_DEFVAL_ON_MISSING 215 * @see JFlag#RETURN_NULL_ON_ANY_ALL 216 * @see JFlag#RETURN_DEFVAL_ON_ANY_ALL 217 */ 218 protected static <T> T JPMEX( 219 JsonObject jo, String propertyName, T defaultValue, int FLAGS, 220 JsonValue.ValueType expectedType, Class<T> returnClass 221 ) 222 { 223 if ((FLAGS & RETURN_NULL_ON_MISSING) != 0) return null; 224 if ((FLAGS & RETURN_DEFVAL_ON_MISSING) != 0) return defaultValue; 225 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 226 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 227 228 throw new JsonPropMissingException(jo, propertyName, expectedType, returnClass); 229 } 230 231 /** 232 * Flag Checker for {@link JsonNullArrException} 233 * 234 * <BR /><BR />Checks whether the relevant flags were set in the users {@code FLAGS} parameter, 235 * and either returns the appropriate value accordingly, or throws 236 * {@code JsonNullArrException}. 237 * 238 * <EMBED CLASS='external-html' DATA-FILE-ID=FLAG_PRECEDENCE> 239 * 240 * @param <T> If requested, the default-value is returned, and this is its type. 241 * 242 * @return Can return either the user-provided default-value, or null depending on whether a 243 * match was found in the user's request settings ({@code 'FLAGS'}). 244 * 245 * @throws JsonNullArrException If no flag was set specifying one of the two return-value 246 * options. 247 * 248 * @see JFlag#RETURN_NULL_ON_NULL 249 * @see JFlag#RETURN_DEFVAL_ON_NULL 250 * @see JFlag#RETURN_NULL_ON_ANY_ALL 251 * @see JFlag#RETURN_DEFVAL_ON_ANY_ALL 252 */ 253 protected static <T> T JNAEX( 254 JsonArray ja, int index, T defaultValue, int FLAGS, JsonValue.ValueType expectedType, 255 Class<T> returnClass 256 ) 257 { 258 if ((FLAGS & RETURN_NULL_ON_NULL) != 0) return null; 259 if ((FLAGS & RETURN_DEFVAL_ON_NULL) != 0) return defaultValue; 260 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 261 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 262 263 throw new JsonNullArrException(ja, index, expectedType, returnClass); 264 } 265 266 /** 267 * Flag Checker for {@link JsonNullObjException} 268 * 269 * <BR /><BR />Checks whether the relevant flags were set in the users {@code FLAGS} parameter, 270 * and either returns the appropriate value accordingly, or throws 271 * {@code JsonNullObjException}. 272 * 273 * <EMBED CLASS='external-html' DATA-FILE-ID=FLAG_PRECEDENCE> 274 * 275 * @param <T> If requested, the default-value is returned, and this is its type. 276 * 277 * @return Can return either the user-provided default-value, or null depending on whether a 278 * match was found in the user's request settings ({@code 'FLAGS'}). 279 * 280 * @throws JsonNullObjException If no flag was set specifying one of the two return-value 281 * options. 282 * 283 * @see JFlag#RETURN_NULL_ON_NULL 284 * @see JFlag#RETURN_DEFVAL_ON_NULL 285 * @see JFlag#RETURN_NULL_ON_ANY_ALL 286 * @see JFlag#RETURN_DEFVAL_ON_ANY_ALL 287 */ 288 protected static <T> T JNOEX( 289 JsonObject jo, String propertyName, T defaultValue, int FLAGS, 290 JsonValue.ValueType expectedType, Class<T> returnClass 291 ) 292 { 293 if ((FLAGS & RETURN_NULL_ON_NULL) != 0) return null; 294 if ((FLAGS & RETURN_DEFVAL_ON_NULL) != 0) return defaultValue; 295 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 296 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 297 298 throw new JsonNullObjException(jo, propertyName, expectedType, returnClass); 299 } 300 301 /** 302 * Flag Checker for {@link JsonTypeArrException} 303 * 304 * <BR /><BR />Checks whether the relevant flags were set in the users {@code FLAGS} parameter, 305 * and either returns the appropriate value accordingly, or throws 306 * {@code JsonTypeArrException}. 307 * 308 * <EMBED CLASS='external-html' DATA-FILE-ID=FLAG_PRECEDENCE> 309 * 310 * @param <T> If requested, the default-value is returned, and this is its type. 311 * 312 * @return Can return either the user-provided default-value, or null depending on whether a 313 * match was found in the user's request settings ({@code 'FLAGS'}). 314 * 315 * @throws JsonTypeArrException If no flag was set specifying one of the two return-value 316 * options. 317 * 318 * @see JFlag#RETURN_NULL_ON_WRONG_JSONTYPE 319 * @see JFlag#RETURN_DEFVAL_ON_WRONG_JSONTYPE 320 * @see JFlag#RETURN_NULL_ON_ANY_ALL 321 * @see JFlag#RETURN_DEFVAL_ON_ANY_ALL 322 */ 323 protected static <T> T JTAEX( 324 JsonArray ja, int index, T defaultValue, int FLAGS, JsonValue.ValueType expectedType, 325 JsonValue retrievedValue, Class<T> returnClass 326 ) 327 { 328 if ((FLAGS & RETURN_NULL_ON_WRONG_JSONTYPE) != 0) return null; 329 if ((FLAGS & RETURN_DEFVAL_ON_WRONG_JSONTYPE) != 0) return defaultValue; 330 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 331 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 332 333 throw new JsonTypeArrException(ja, index, expectedType, retrievedValue, returnClass); 334 } 335 336 /** 337 * Flag Checker for {@link JsonTypeObjException} 338 * 339 * <BR /><BR />Checks whether the relevant flags were set in the users {@code FLAGS} parameter, 340 * and either returns the appropriate value accordingly, or throws 341 * {@code JsonNullObjException}. 342 * 343 * <EMBED CLASS='external-html' DATA-FILE-ID=FLAG_PRECEDENCE> 344 * 345 * @param <T> If requested, the default-value is returned, and this is its type. 346 * 347 * @return Can return either the user-provided default-value, or null depending on whether a 348 * match was found in the user's request settings ({@code 'FLAGS'}). 349 * 350 * @throws JsonNullObjException If no flag was set specifying one of the two return-value 351 * options. 352 * 353 * @see JFlag#RETURN_NULL_ON_WRONG_JSONTYPE 354 * @see JFlag#RETURN_DEFVAL_ON_WRONG_JSONTYPE 355 * @see JFlag#RETURN_NULL_ON_ANY_ALL 356 * @see JFlag#RETURN_DEFVAL_ON_ANY_ALL 357 */ 358 protected static <T> T JTOEX( 359 JsonObject jo, String propertyName, T defaultValue, int FLAGS, 360 JsonValue.ValueType expectedType, JsonValue retrievedValue, Class<T> returnClass 361 ) 362 { 363 if ((FLAGS & RETURN_NULL_ON_WRONG_JSONTYPE) != 0) return null; 364 if ((FLAGS & RETURN_DEFVAL_ON_WRONG_JSONTYPE) != 0) return defaultValue; 365 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 366 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 367 368 throw new JsonTypeObjException 369 (jo, propertyName, expectedType, retrievedValue, returnClass); 370 } 371 372 /** 373 * Flag Checker for {@link JsonStrParseArrException} 374 * 375 * <BR /><BR />Checks whether the relevant flags were set in the users {@code FLAGS} parameter, 376 * and either returns the appropriate value accordingly, or throws 377 * {@code JsonStrParseArrException}. 378 * 379 * <EMBED CLASS='external-html' DATA-FILE-ID=FLAG_PRECEDENCE> 380 * 381 * @param <T> If requested, the default-value is returned, and this is its type. 382 * 383 * @return Can return either the user-provided default-value, or null depending on whether a 384 * match was found in the user's request settings ({@code 'FLAGS'}). 385 * 386 * @throws JsonStrParseArrException If no flag was set specifying one of the two return-value 387 * options. 388 * 389 * @see JFlag#RETURN_NULL_ON_SPEX 390 * @see JFlag#RETURN_DEFVAL_ON_SPEX 391 * @see JFlag#RETURN_NULL_ON_ANY_ALL 392 * @see JFlag#RETURN_DEFVAL_ON_ANY_ALL 393 */ 394 protected static <T> T JSPAEX( 395 Exception e, JsonArray ja, int index, T defaultValue, int FLAGS, 396 JsonValue retrievedValue, Class<T> returnClass 397 ) 398 { 399 if ((FLAGS & RETURN_NULL_ON_SPEX) != 0) return null; 400 if ((FLAGS & RETURN_DEFVAL_ON_SPEX) != 0) return defaultValue; 401 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 402 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 403 404 throw new JsonStrParseArrException(e, ja, index, retrievedValue, returnClass); 405 } 406 407 /** 408 * Flag Checker for {@link JsonStrParseObjException} 409 * 410 * <BR /><BR />Checks whether the relevant flags were set in the users {@code FLAGS} parameter, 411 * and either returns the appropriate value accordingly, or throws 412 * {@code JsonStrParseObjException}. 413 * 414 * <EMBED CLASS='external-html' DATA-FILE-ID=FLAG_PRECEDENCE> 415 * 416 * @param <T> If requested, the default-value is returned, and this is its type. 417 * 418 * @return Can return either the user-provided default-value, or null depending on whether a 419 * match was found in the user's request settings ({@code 'FLAGS'}). 420 * 421 * @throws JsonStrParseObjException If no flag was set specifying one of the two return-value 422 * options. 423 * 424 * @see JFlag#RETURN_NULL_ON_SPEX 425 * @see JFlag#RETURN_DEFVAL_ON_SPEX 426 * @see JFlag#RETURN_NULL_ON_ANY_ALL 427 * @see JFlag#RETURN_DEFVAL_ON_ANY_ALL 428 */ 429 protected static <T> T JSPOEX( 430 Exception e, JsonObject jo, String propertyName, T defaultValue, int FLAGS, 431 JsonValue retrievedValue, Class<T> returnClass 432 ) 433 { 434 if ((FLAGS & RETURN_NULL_ON_SPEX) != 0) return null; 435 if ((FLAGS & RETURN_DEFVAL_ON_SPEX) != 0) return defaultValue; 436 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 437 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 438 439 throw new JsonStrParseObjException(e, jo, propertyName, retrievedValue, returnClass); 440 } 441 442 443}