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 />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=JDDescLabel>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 ReadNumberJSON#get(JsonObject, String, int, Number)
144     * @see ReadNumberJSON#get(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 ReadNumberJSON#parse(JsonObject, String, int, Number, Function)
187     * @see ReadNumberJSON#parse(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 ReadPrimJSON#getInt(JsonArray, int)
253     * @see ReadPrimJSON#getLong(JsonArray, int)
254     * @see ReadPrimJSON#getShort(JsonArray, int)
255     * @see ReadPrimJSON#getByte(JsonArray, int)
256     * @see ReadPrimJSON#getDouble(JsonArray, int)
257     * @see ReadPrimJSON#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 ReadBoxedJSON#getInteger(JsonArray, int)
311     * @see ReadBoxedJSON#getLong(JsonArray, int)
312     * @see ReadBoxedJSON#getShort(JsonArray, int)
313     * @see ReadBoxedJSON#getByte(JsonArray, int)
314     * @see ReadBoxedJSON#getDouble(JsonArray, int)
315     * @see ReadBoxedJSON#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 ReadPrimJSON#getInt(JsonObject, String)
375     * @see ReadPrimJSON#getLong(JsonObject, String)
376     * @see ReadPrimJSON#getShort(JsonObject, String)
377     * @see ReadPrimJSON#getByte(JsonObject, String)
378     * @see ReadPrimJSON#getDouble(JsonObject, String)
379     * @see ReadPrimJSON#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 ReadBoxedJSON#getInteger(JsonObject, String, boolean)
442     * @see ReadBoxedJSON#getLong(JsonObject, String, boolean)
443     * @see ReadBoxedJSON#getShort(JsonObject, String, boolean)
444     * @see ReadBoxedJSON#getByte(JsonObject, String, boolean)
445     * @see ReadBoxedJSON#getDouble(JsonObject, String, boolean)
446     * @see ReadBoxedJSON#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 ReadBoxedJSON#getInteger(JsonArray, int, int, int)
808     * @see ReadBoxedJSON#getLong(JsonArray, int, int, long)
809     * @see ReadBoxedJSON#getShort(JsonArray, int, int, short)
810     * @see ReadBoxedJSON#getByte(JsonArray, int, int, byte)
811     * @see ReadBoxedJSON#getDouble(JsonArray, int, int, double)
812     * @see ReadBoxedJSON#getFloat(JsonArray, int, int, float)
813     * @see ReadNumberJSON#get(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 ReadBoxedJSON#getInteger(JsonObject, String, int, int)
910     * @see ReadBoxedJSON#getLong(JsonObject, String, int, long)
911     * @see ReadBoxedJSON#getShort(JsonObject, String, int, short)
912     * @see ReadBoxedJSON#getByte(JsonObject, String, int, byte)
913     * @see ReadBoxedJSON#getDouble(JsonObject, String, int, double)
914     * @see ReadBoxedJSON#getFloat(JsonObject, String, int, float)
915     * @see ReadNumberJSON#get(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 ReadBoxedJSON#parseInteger(JsonArray, int, int, int, Function)
1027     * @see ReadBoxedJSON#parseLong(JsonArray, int, int, long, Function)
1028     * @see ReadBoxedJSON#parseShort(JsonArray, int, int, short, Function)
1029     * @see ReadBoxedJSON#parseByte(JsonArray, int, int, byte, Function)
1030     * @see ReadBoxedJSON#parseDouble(JsonArray, int, int, double, Function)
1031     * @see ReadBoxedJSON#parseFloat(JsonArray, int, int, float, Function)
1032     * @see ReadNumberJSON#parse(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 ReadBoxedJSON#parseInteger(JsonObject, String, int, int, Function)
1160     * @see ReadBoxedJSON#parseLong(JsonObject, String, int, long, Function)
1161     * @see ReadBoxedJSON#parseShort(JsonObject, String, int, short, Function)
1162     * @see ReadBoxedJSON#parseByte(JsonObject, String, int, byte, Function)
1163     * @see ReadBoxedJSON#parseDouble(JsonObject, String, int, double, Function)
1164     * @see ReadBoxedJSON#parseFloat(JsonObject, String, int, float, Function)
1165     * @see ReadNumberJSON#parse(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}