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}