001package Torello.JSON;
002
003import Torello.JavaDoc.Annotations.IntoHTMLTable;
004import static Torello.JavaDoc.Annotations.IntoHTMLTable.Background.BlueDither;
005import static Torello.JavaDoc.Annotations.IntoHTMLTable.Background.GreenDither;
006
007import static javax.json.JsonValue.ValueType.*;
008import static Torello.JSON.RJInternal.*;
009import static Torello.JSON.JFlag.*;
010
011import javax.json.JsonObject;
012import javax.json.JsonArray;
013import javax.json.JsonString;
014import javax.json.JsonNumber;
015import javax.json.JsonValue;
016
017import java.math.BigDecimal;
018
019import java.util.function.Function;
020
021/**
022 * Builds on the J2EE Standard Release JSON Parsing Tools by providing additional
023 * help with converting JSON Data into <B STYLE='color: red'>Java Boxed-Primitive Types</B>
024 * 
025 * <EMBED CLASS='external-html' DATA-FILE-ID=ALL_CLASSES_NOTE>
026 * <EMBED CLASS='external-html' DATA-FILE-ID=READ_BOXED_JSON>
027 * <EMBED CLASS='external-html' DATA-FILE-ID=READ_BOXED_PTABLE>
028 * <EMBED CLASS='external-html' DATA-CH='java.lang.Character' DATA-FILE-ID=JAVA_LANG_CHAR>
029 * 
030 * @see JsonObject
031 * @see JsonArray
032 */
033@Torello.JavaDoc.Annotations.StaticFunctional
034public class ReadBoxedJSON
035{
036    // This is a static class.  Has no program state.
037    private ReadBoxedJSON() { }
038
039
040    // ********************************************************************************************
041    // ********************************************************************************************
042    // From JsonArray, No Error Control Flags
043    // ********************************************************************************************
044    // ********************************************************************************************
045
046
047    /**
048     * <EMBED CLASS='external-html' DATA-TYPE=Integer DATA-FILE-ID=READ_BOXED_NF_JA>
049     * @see #GET_NO_FLAGS(JsonArray, int, Function, Class)
050     * @see JsonNumber#intValueExact()
051     */
052    @IntoHTMLTable(
053        title="Retrieve a JsonArray element, and transform it to a Java Boxed Integer",
054        background=BlueDither
055    )
056    public static Integer getInteger(final JsonArray ja, final int index)
057    { return GET_NO_FLAGS(ja, index, JsonNumber::intValueExact, Integer.class); }
058
059    /**
060     * <EMBED CLASS='external-html' DATA-TYPE=Long DATA-FILE-ID=READ_BOXED_NF_JA>
061     * @see #GET_NO_FLAGS(JsonArray, int, Function, Class)
062     * @see JsonNumber#longValueExact()
063     */
064    @IntoHTMLTable(
065        title="Retrieve a JsonArray element, and transform it to a Boxed Long Integer",
066        background=GreenDither
067    )
068    public static Long getLong(final JsonArray ja, final int index)
069    { return GET_NO_FLAGS(ja, index, JsonNumber::longValueExact, Long.class); }
070
071    /**
072     * <EMBED CLASS='external-html' DATA-TYPE=Long DATA-FILE-ID=READ_BOXED_NF_JA>
073     * @see #GET_NO_FLAGS(JsonArray, int, Function, Class)
074     * @see JsonNumber#bigDecimalValue()
075     */
076    @IntoHTMLTable(
077        title="Retrieve a JsonArray element, and transform it to a Boxed Short Integer",
078        background=BlueDither
079    )
080    public static Short getShort(final JsonArray ja, final int index)
081    { return GET_NO_FLAGS(ja, index, jn -> jn.bigDecimalValue().shortValueExact(), Short.class); }
082
083    /**
084     * <EMBED CLASS='external-html' DATA-TYPE=Byte DATA-FILE-ID=READ_BOXED_NF_JA>
085     * @see #GET_NO_FLAGS(JsonArray, int, Function, Class)
086     * @see JsonNumber#bigDecimalValue()
087     */
088    @IntoHTMLTable(
089        title="Retrieve a JsonArray element, and transform it to a Java Boxed Byte",
090        background=GreenDither
091    )
092    public static Byte getByte(final JsonArray ja, final int index)
093    { return GET_NO_FLAGS(ja, index, jn -> jn.bigDecimalValue().byteValueExact(), Byte.class); }
094
095    /**
096     * <EMBED CLASS='external-html' DATA-TYPE=Double DATA-FILE-ID=READ_BOXED_NF_JA>
097     * @see #GET_NO_FLAGS(JsonArray, int, Function, Class)
098     * @see RJInternal#DOUBLE_WITH_CHECK(JsonNumber)
099     */
100    @IntoHTMLTable(
101        title="Retrieve a JsonArray element, and transform it to a Java Boxed Double",
102        background=BlueDither
103    )
104    public static Double getDouble(final JsonArray ja, final int index)
105    { return GET_NO_FLAGS(ja, index, RJInternal::DOUBLE_WITH_CHECK, Double.class); }
106
107    /**
108     * <EMBED CLASS='external-html' DATA-TYPE=Float DATA-FILE-ID=READ_BOXED_NF_JA>
109     * @see #GET_NO_FLAGS(JsonArray, int, Function, Class)
110     * @see RJInternal#FLOAT_WITH_CHECK(JsonNumber)
111     */
112    @IntoHTMLTable(
113        title="Retrieve a JsonArray element, and transform it to a Java Boxed Float",
114        background=GreenDither
115    )
116    public static Float getFloat(final JsonArray ja, final int index)
117    { return GET_NO_FLAGS(ja, index, RJInternal::FLOAT_WITH_CHECK, Float.class); }
118
119    /**
120     * <EMBED CLASS='external-html' DATA-TYPE=Boolean DATA-FILE-ID=READ_BOXED_NF_JA>
121     * @see JsonValue#getValueType()
122     * @see JsonValue.ValueType#TRUE
123     * @see JsonValue.ValueType#FALSE
124     * @see JsonValue#TRUE
125     * @see JsonValue#FALSE
126     */
127    @IntoHTMLTable(
128        title="Retrieve a JsonArray element, and transform it to a Java Boxed Boolean",
129        background=BlueDither
130    )
131    public static Boolean getBoolean(final JsonArray ja, final int index)
132    {
133        final JsonValue jv = ja.get(index);
134
135        switch (jv.getValueType())
136        {
137            case NULL:  return null;
138            case TRUE:  return true;
139            case FALSE: return false;
140            default:    throw new JsonTypeArrException(ja, index, TRUE, jv, Boolean.class);
141        }
142    }
143
144
145    // ********************************************************************************************
146    // ********************************************************************************************
147    // From JsonObject, No Error Control Flags
148    // ********************************************************************************************
149    // ********************************************************************************************
150
151
152    /**
153     * <EMBED CLASS='external-html' DATA-TYPE=Integer DATA-FILE-ID=READ_BOXED_NF_JO>
154     * @see #GET_NO_FLAGS(JsonObject, String, boolean, Function, Class)
155     * @see JsonNumber#intValueExact()
156     */
157    @IntoHTMLTable(
158        title="Retrieve a JsonObject property, and transform it to a Java Boxed Integer",
159        background=GreenDither
160    )
161    public static Integer getInteger(
162            final JsonObject    jo,
163            final String        propertyName,
164            final boolean       isOptional
165        )
166    {
167        return GET_NO_FLAGS
168            (jo, propertyName, isOptional, JsonNumber::intValueExact, Integer.class);
169    }
170
171    /**
172     * <EMBED CLASS='external-html' DATA-TYPE=Long DATA-FILE-ID=READ_BOXED_NF_JO>
173     * @see #GET_NO_FLAGS(JsonObject, String, boolean, Function, Class)
174     * @see JsonNumber#longValueExact()
175     */
176    @IntoHTMLTable(
177        title="Retrieve a JsonObject property, and transform it to a Boxed Long Integer",
178        background=BlueDither
179    )
180    public static Long getLong(
181            final JsonObject    jo,
182            final String        propertyName,
183            final boolean       isOptional
184        )
185    {
186        return GET_NO_FLAGS
187            (jo, propertyName, isOptional, JsonNumber::longValueExact, Long.class);
188    }
189
190    /**
191     * <EMBED CLASS='external-html' DATA-TYPE=Short DATA-FILE-ID=READ_BOXED_NF_JO>
192     * @see #GET_NO_FLAGS(JsonObject, String, boolean, Function, Class)
193     * @see JsonNumber#bigDecimalValue()
194     */
195    @IntoHTMLTable(
196        title="Retrieve a JsonObject property, and transform it to a Boxed Short Integer",
197        background=GreenDither
198    )
199    public static Short getShort(
200            final JsonObject    jo,
201            final String        propertyName,
202            final boolean       isOptional
203        )
204    {
205        return GET_NO_FLAGS(
206            jo, propertyName, isOptional,
207            jn -> jn.bigDecimalValue().shortValueExact(),
208            Short.class
209        );
210    }
211
212    /**
213     * <EMBED CLASS='external-html' DATA-TYPE=Byte DATA-FILE-ID=READ_BOXED_NF_JO>
214     * @see #GET_NO_FLAGS(JsonObject, String, boolean, Function, Class)
215     * @see JsonNumber#bigDecimalValue()
216     */
217    @IntoHTMLTable(
218        title="Retrieve a JsonObject property, and transform it to a Java Boxed Byte",
219        background=BlueDither
220    )
221    public static Byte getByte(
222            final JsonObject    jo,
223            final String        propertyName,
224            final boolean       isOptional
225        )
226    {
227        return GET_NO_FLAGS(
228            jo, propertyName, isOptional,
229            jn -> jn.bigDecimalValue().byteValueExact(),
230            Byte.class
231        );
232    }
233
234    /**
235     * <EMBED CLASS='external-html' DATA-TYPE=Double DATA-FILE-ID=READ_BOXED_NF_JO>
236     * @see #GET_NO_FLAGS(JsonObject, String, boolean, Function, Class)
237     * @see RJInternal#DOUBLE_WITH_CHECK(JsonNumber)
238     */
239    @IntoHTMLTable(
240        title="Retrieve a JsonObject property, and transform it to a Java Boxed Double",
241        background=GreenDither
242    )
243    public static Double getDouble(
244            final JsonObject    jo,
245            final String        propertyName,
246            final boolean       isOptional
247        )
248    {
249        return GET_NO_FLAGS
250            (jo, propertyName, isOptional, RJInternal::DOUBLE_WITH_CHECK, Double.class);
251    }
252
253    /**
254     * <EMBED CLASS='external-html' DATA-TYPE=Float DATA-FILE-ID=READ_BOXED_NF_JO>
255     * @see #GET_NO_FLAGS(JsonObject, String, boolean, Function, Class)
256     * @see RJInternal#FLOAT_WITH_CHECK(JsonNumber)
257     */
258    @IntoHTMLTable(
259        title="Retrieve a JsonObject property, and transform it to a Java Boxed Float",
260        background=BlueDither
261    )
262    public static Float getFloat(
263            final JsonObject    jo,
264            final String        propertyName,
265            final boolean       isOptional
266        )
267    {
268        return GET_NO_FLAGS
269            (jo, propertyName, isOptional, RJInternal::FLOAT_WITH_CHECK, Float.class);
270    }
271
272    /**
273     * <EMBED CLASS='external-html' DATA-TYPE=Boolean DATA-FILE-ID=READ_BOXED_NF_JO>
274     * @see JsonValue#getValueType()
275     * @see JsonValue.ValueType#TRUE
276     * @see JsonValue.ValueType#FALSE
277     * @see JsonValue#TRUE
278     * @see JsonValue#FALSE
279     */
280    @IntoHTMLTable(
281        title="Retrieve a JsonObject property, and transform it to a Java Boxed Boolean",
282        background=GreenDither
283    )
284    public static Boolean getBoolean(
285            final JsonObject    jo,
286            final String        propertyName,
287            final boolean       isOptional
288        )
289    {
290        if (! jo.containsKey(propertyName))
291        {
292            if (isOptional) return null;
293            throw new JsonPropMissingException(jo, propertyName, TRUE, Boolean.class);
294        }
295
296        final JsonValue jv = jo.get(propertyName);
297
298        switch (jv.getValueType())
299        {
300            case NULL:  return null;
301            case TRUE:  return true;
302            case FALSE: return false;
303            default:    throw new JsonTypeObjException(jo, propertyName, TRUE, jv, Boolean.class);
304        }
305    }
306
307
308    // ********************************************************************************************
309    // ********************************************************************************************
310    // From JsonArray, WITH FLAGS
311    // ********************************************************************************************
312    // ********************************************************************************************
313
314
315    /**
316     * <EMBED CLASS='external-html' DATA-TYPE=Integer DATA-FILE-ID=READ_BOXED_WF_JA>
317     * @see #GET(JsonArray, int, int, Number, Class, Function, Function)
318     * @see JsonNumber#intValueExact()
319     * @see JsonNumber#intValue()
320     */
321    @IntoHTMLTable(
322        title="Retrieve a JsonArray element, and transform it to a Java Boxed Integer",
323        background=BlueDither
324    )
325    public static Integer getInteger(
326            final JsonArray ja,
327            final int       index,
328            final int       FLAGS,
329            final int       defaultValue
330        )
331    {
332        return GET(
333            ja, index, FLAGS, defaultValue,
334            Integer.class, JsonNumber::intValueExact, JsonNumber::intValue
335        );
336    }
337
338    /**
339     * <EMBED CLASS='external-html' DATA-TYPE=Long DATA-FILE-ID=READ_BOXED_WF_JA>
340     * @see #GET(JsonArray, int, int, Number, Class, Function, Function)
341     * @see JsonNumber#longValueExact()
342     * @see JsonNumber#longValue()
343     */
344    @IntoHTMLTable(
345        title="Retrieve a JsonArray element, and transform it to a Boxed Long Integer",
346        background=GreenDither
347    )
348    public static Long getLong(
349            final JsonArray ja,
350            final int       index,
351            final int       FLAGS,
352            final long      defaultValue
353        )
354    {
355        return GET(
356            ja, index, FLAGS, defaultValue,
357            Long.class, JsonNumber::longValueExact, JsonNumber::longValue
358        );
359    }
360
361    /**
362     * <EMBED CLASS='external-html' DATA-TYPE=Short DATA-FILE-ID=READ_BOXED_WF_JA>
363     * @see #GET(JsonArray, int, int, Number, Class, Function, Function)
364     * @see JsonNumber#bigDecimalValue()
365     */
366    @IntoHTMLTable(
367        title="Retrieve a JsonArray element, and transform it to a Boxed Short Integer",
368        background=BlueDither
369    )
370    public static Short getShort(
371            final JsonArray ja,
372            final int       index,
373            final int       FLAGS,
374            final short     defaultValue
375        )
376    {
377        return GET(
378            ja, index, FLAGS, defaultValue, Short.class,
379            jn -> jn.bigDecimalValue().shortValueExact(),
380            jn -> jn.bigDecimalValue().shortValue()
381        );
382    }
383
384    /**
385     * <EMBED CLASS='external-html' DATA-TYPE=Byte DATA-FILE-ID=READ_BOXED_WF_JA>
386     * @see #GET(JsonArray, int, int, Number, Class, Function, Function)
387     * @see JsonNumber#bigDecimalValue()
388     */
389    @IntoHTMLTable(
390        title="Retrieve a JsonArray element, and transform it to a Java Boxed Byte",
391        background=GreenDither
392    )
393    public static Byte getByte(
394            final JsonArray ja,
395            final int       index,
396            final int       FLAGS,
397            final byte      defaultValue
398        )
399    {
400        return GET(
401            ja, index, FLAGS, defaultValue, Byte.class,
402            jn -> jn.bigDecimalValue().byteValueExact(),
403            jn -> jn.bigDecimalValue().byteValue()
404        );
405    }
406
407    /**
408     * <EMBED CLASS='external-html' DATA-TYPE=Double DATA-FILE-ID=READ_BOXED_WF_JA>
409     * @see #GET(JsonArray, int, int, Number, Class, Function, Function)
410     * @see RJInternal#DOUBLE_WITH_CHECK(JsonNumber)
411     * @see JsonNumber#bigDecimalValue()
412     */
413    @IntoHTMLTable(
414        title="Retrieve a JsonArray element, and transform it to a Java Boxed Double",
415        background=BlueDither
416    )
417    public static Double getDouble(
418            final JsonArray ja,
419            final int       index,
420            final int       FLAGS,
421            final double    defaultValue
422        )
423    {
424        return GET(
425            ja, index, FLAGS, defaultValue, Double.class,
426            RJInternal::DOUBLE_WITH_CHECK,
427            jn -> jn.bigDecimalValue().doubleValue()
428        );
429    }
430
431    /**
432     * <EMBED CLASS='external-html' DATA-TYPE=Float DATA-FILE-ID=READ_BOXED_WF_JA>
433     * @see #GET(JsonArray, int, int, Number, Class, Function, Function)
434     * @see RJInternal#FLOAT_WITH_CHECK(JsonNumber)
435     * @see JsonNumber#bigDecimalValue()
436     */
437    @IntoHTMLTable(
438        title="Retrieve a JsonArray element, and transform it to a Java Boxed Float",
439        background=GreenDither
440    )
441    public static Float getFloat(
442            final JsonArray ja,
443            final int       index,
444            final int       FLAGS,
445            final float     defaultValue
446        )
447    {
448        return GET(
449            ja, index, FLAGS, defaultValue, Float.class,
450            RJInternal::FLOAT_WITH_CHECK,
451            jn -> jn.bigDecimalValue().floatValue()
452        );
453    }
454
455    /**
456     * <EMBED CLASS='external-html' DATA-TYPE=Boolean DATA-FILE-ID=READ_BOXED_WF_JA>
457     * @see JsonValue#getValueType()
458     * @see JsonValue.ValueType#TRUE
459     * @see JsonValue.ValueType#FALSE
460     * @see JsonValue#TRUE
461     * @see JsonValue#FALSE
462     */
463    @IntoHTMLTable(
464        title="Retrieve a JsonArray element, and transform it to a Java Boxed Boolean",
465        background=BlueDither
466    )
467    public static Boolean getBoolean(
468            final JsonArray ja,
469            final int       index,
470            final int       FLAGS,
471            final boolean   defaultValue
472        )
473    {
474        if (index >= ja.size()) return IOOBEX(ja, index, defaultValue, FLAGS);
475
476        final JsonValue jv = ja.get(index); // Throw an IndexOutOfBoundsException
477
478        switch (jv.getValueType())
479        {
480            case NULL:  return JNAEX(ja, index, defaultValue, FLAGS, TRUE, Boolean.class);
481            case TRUE:  return true;
482            case FALSE: return false;
483            default:    return JTAEX(ja, index, defaultValue, FLAGS, TRUE, jv, Boolean.class);
484        }
485    }
486
487
488    // ********************************************************************************************
489    // ********************************************************************************************
490    // From JsonObject, WITH FLAGS
491    // ********************************************************************************************
492    // ********************************************************************************************
493
494
495    /**
496     * <EMBED CLASS='external-html' DATA-TYPE=Integer DATA-FILE-ID=READ_BOXED_WF_JO>
497     * @see #GET(JsonObject, String, int, Number, Class, Function, Function)
498     * @see JsonNumber#intValueExact()
499     * @see JsonNumber#intValue()
500     */
501    @IntoHTMLTable(
502        title="Retrieve a JsonObject property, and transform it to a Java Boxed Integer",
503        background=GreenDither
504    )
505    public static Integer getInteger(
506            final JsonObject    jo,
507            final String        propertyName,
508            final int           FLAGS,
509            final int           defaultValue
510        )
511    {
512        return GET(
513            jo, propertyName, FLAGS, defaultValue,
514            Integer.class, JsonNumber::intValueExact, JsonNumber::intValue
515        );
516    }
517
518    /**
519     * <EMBED CLASS='external-html' DATA-TYPE=Long DATA-FILE-ID=READ_BOXED_WF_JO>
520     * @see #GET(JsonObject, String, int, Number, Class, Function, Function)
521     * @see JsonNumber#longValueExact()
522     * @see JsonNumber#longValue()
523     */
524    @IntoHTMLTable(
525        title="Retrieve a JsonObject property, and transform it to a Boxed Long Integer",
526        background=BlueDither
527    )
528    public static Long getLong(
529            final JsonObject    jo,
530            final String        propertyName,
531            final int           FLAGS,
532            final long          defaultValue
533        )
534    {
535        return GET(
536            jo, propertyName, FLAGS, defaultValue,
537            Long.class, JsonNumber::longValueExact, JsonNumber::longValue
538        );
539    }
540
541    /**
542     * <EMBED CLASS='external-html' DATA-TYPE=Short DATA-FILE-ID=READ_BOXED_WF_JO>
543     * @see #GET(JsonObject, String, int, Number, Class, Function, Function)
544     * @see JsonNumber#bigDecimalValue()
545     */
546    @IntoHTMLTable(
547        title="Retrieve a JsonObject property, and transform it to a Boxed Short Integer",
548        background=GreenDither
549    )
550    public static Short getShort(
551            final JsonObject    jo,
552            final String        propertyName,
553            final int           FLAGS,
554            final short         defaultValue
555        )
556    {
557        return GET(
558            jo, propertyName, FLAGS, defaultValue,
559            Short.class,
560            jn -> jn.bigDecimalValue().shortValueExact(),
561            jn -> jn.bigDecimalValue().shortValue()
562        );
563    }
564
565    /**
566     * <EMBED CLASS='external-html' DATA-TYPE=Byte DATA-FILE-ID=READ_BOXED_WF_JO>
567     * @see #GET(JsonObject, String, int, Number, Class, Function, Function)
568     * @see JsonNumber#bigDecimalValue()
569     */
570    @IntoHTMLTable(
571        title="Retrieve a JsonObject property, and transform it to a Java Boxed Byte",
572        background=BlueDither
573    )
574    public static Byte getByte(
575            final JsonObject    jo,
576            final String        propertyName,
577            final int           FLAGS,
578            final byte          defaultValue
579        )
580    {
581        return GET(
582            jo, propertyName, FLAGS, defaultValue,
583            Byte.class,
584            jn -> jn.bigDecimalValue().byteValueExact(),
585            jn -> jn.bigDecimalValue().byteValue()
586        );
587    }
588
589    /**
590     * <EMBED CLASS='external-html' DATA-TYPE=Double DATA-FILE-ID=READ_BOXED_WF_JO>
591     * @see #GET(JsonObject, String, int, Number, Class, Function, Function)
592     * @see RJInternal#DOUBLE_WITH_CHECK(JsonNumber)
593     * @see JsonNumber#bigDecimalValue()
594     */
595    @IntoHTMLTable(
596        title="Retrieve a JsonObject property, and transform it to a Java Boxed Double",
597        background=GreenDither
598    )
599    public static Double getDouble(
600            final JsonObject    jo,
601            final String        propertyName,
602            final int           FLAGS,
603            final double        defaultValue
604        )
605    {
606        return GET(
607            jo, propertyName, FLAGS, defaultValue,
608            Double.class,
609            RJInternal::DOUBLE_WITH_CHECK,
610            jn -> jn.bigDecimalValue().doubleValue()
611        );
612    }
613
614    /**
615     * <EMBED CLASS='external-html' DATA-TYPE=Float DATA-FILE-ID=READ_BOXED_WF_JO>
616     * @see #GET(JsonObject, String, int, Number, Class, Function, Function)
617     * @see RJInternal#FLOAT_WITH_CHECK(JsonNumber)
618     * @see JsonNumber#bigDecimalValue()
619     */
620    @IntoHTMLTable(
621        title="Retrieve a JsonObject property, and transform it to a Java Boxed Float",
622        background=BlueDither
623    )
624    public static Float getFloat(
625            final JsonObject    jo,
626            final String        propertyName,
627            final int           FLAGS,
628            final float         defaultValue
629        )
630    {
631        return GET(
632            jo, propertyName, FLAGS, defaultValue,
633            Float.class,
634            RJInternal::FLOAT_WITH_CHECK,
635            jn -> jn.bigDecimalValue().floatValue()
636        );
637    }
638
639    /**
640     * <EMBED CLASS='external-html' DATA-TYPE=Boolean DATA-FILE-ID=READ_BOXED_WF_JO>
641     * @see JsonValue#getValueType()
642     * @see JsonValue.ValueType#TRUE
643     * @see JsonValue.ValueType#FALSE
644     * @see JsonValue#TRUE
645     * @see JsonValue#FALSE
646     */
647    @IntoHTMLTable(
648        title="Retrieve a JsonObject property, and transform it to a Java Boxed Boolean",
649        background=GreenDither
650    )
651    public static Boolean getBoolean(
652            final JsonObject    jo,
653            final String        propertyName,
654            final int           FLAGS,
655            final boolean       defaultValue
656        )
657    {
658        final JsonValue jv = jo.get(propertyName);
659
660        if (jv == null) return JPMEX(jo, propertyName, defaultValue, FLAGS, TRUE, Boolean.class);
661
662        switch (jv.getValueType())
663        {
664            case NULL:  return JNOEX(jo, propertyName, defaultValue, FLAGS, TRUE, Boolean.class);
665            case TRUE:  return true;
666            case FALSE: return false;
667
668            default:
669                return JTOEX(jo, propertyName, defaultValue, FLAGS, TRUE, jv, Boolean.class);
670        }
671    }
672
673
674    // ********************************************************************************************
675    // ********************************************************************************************
676    // PROTECTED, INTERNAL METHODS FOR NUMBERS
677    // ********************************************************************************************
678    // ********************************************************************************************
679
680
681    /**
682     * This is an internal helper method for retrieving an element from a {@link JsonArray},
683     * and converting it to one of the standard <B STYLE='color: red;'>Java Types</B>.
684     *  
685     * @param <T>                   Numeric Boxed-Type, as an instance of {@code java.lang.Class}
686     * @param ja                    Any instance of {@link JsonArray}
687     * @param index                 A valid index into {@code 'ja'}
688     * @param jsonTypeToJavaType    <EMBED CLASS='external-html' DATA-FILE-ID=READ_BOXED_JTTJT>
689     * 
690     * @return The converted number, as an instance Generic-Parameter {@code 'T'}
691     * 
692     * @throws JsonTypeArrException If array index specified does not contain a {@link JsonNumber}
693     * @throws JsonArithmeticArrException If there any arithmetic problems during the conversion
694     * @throws IndexOutOfBoundsException If {@code 'index'} is out of the bounds of {@code 'ja'}
695     * 
696     * @see #getInteger(JsonArray, int)
697     * @see #getLong(JsonArray, int)
698     * @see #getShort(JsonArray, int)
699     * @see #getByte(JsonArray, int)
700     * @see #getDouble(JsonArray, int)
701     * @see #getFloat(JsonArray, int)
702     */
703    protected static <T extends java.lang.Number> T GET_NO_FLAGS(
704            final JsonArray                 ja,
705            final int                       index,
706            final Function<JsonNumber, T>   jsonTypeToJavaType,
707            final Class<T>                  returnClass
708        )
709    {
710        // This will throw an IndexOutOfBoundsException if the index is out of bounds.
711        // Since this *IS NOT* a method with FLAGS, the user has no way to avoid this exception
712        // throw if, indeed, the index really is out of bounds!
713        //
714        // Using one of the 'FLAGS' variants of the 'GET' array-index, a user may request that
715        // either null or a default-value be returned.  Not with this version-of 'GET', though.
716
717        final JsonValue jv = ja.get(index);
718
719        switch (jv.getValueType())
720        {
721            // This method allows for null-returns.  If Json-Null, return Java-Null.
722            case NULL: return null;
723
724            // This will throw ArithmeticException if it cannot be converted
725            case NUMBER:
726
727                // REMEMBER: The primary reason for this class is that MEANINGFUL ERROR MESSAGES
728                //           make Json-Binding a lot easer...  "JsonArithmeticException" has just
729                //           about everything that you need to know when debugging this stuff
730
731                try
732                    { return jsonTypeToJavaType.apply((JsonNumber) jv); }
733
734                catch (ArithmeticException ae)
735                {
736                    throw new JsonArithmeticArrException
737                        (ae, ja, index, NUMBER, jv, returnClass);
738                }
739
740            // The JsonValue at the specified array-index does not contain an JsonNumber.
741            default: throw new JsonTypeArrException
742                (ja, index, NUMBER, jv, returnClass);
743        }
744    }
745
746    /**
747     * This is an internal helper method for retrieving a property from a {@link JsonObject},
748     * and converting it to one of the standard <B STYLE='color: red;'>Java Types</B>.
749     * 
750     * @param <T>                   Numeric Boxed-Type, as an instance of {@code java.lang.Class}
751     * @param jo                    Any instance of {@link JsonObject}
752     * @param propertyName          Any property name contained by {@code 'jo'}
753     * @param isOptional            <EMBED CLASS='external-html' DATA-FILE-ID=COMMON_IS_OPTIONAL>
754     * @param jsonTypeToJavaType    <EMBED CLASS='external-html' DATA-FILE-ID=READ_BOXED_JTTJT>
755     * 
756     * @return The converted number, as an instance of Generic-Parameter {@code 'T'}
757     * 
758     * @throws JsonPropMissingException If the property is missing, and {@code 'isOptional'}
759     * is {@code FALSE}.
760     * @throws JsonTypeObjException If the property specified does not contain a {@link JsonNumber}
761     * @throws JsonArithmeticObjException If there any arithmetic problems during the conversion
762     * 
763     * @see #getInteger(JsonObject, String, boolean)
764     * @see #getLong(JsonObject, String, boolean)
765     * @see #getShort(JsonObject, String, boolean)
766     * @see #getByte(JsonObject, String, boolean)
767     * @see #getDouble(JsonObject, String, boolean)
768     * @see #getFloat(JsonObject, String, boolean)
769     */
770    protected static <T extends java.lang.Number> T GET_NO_FLAGS(
771            final JsonObject                jo,
772            final String                    propertyName,
773            final boolean                   isOptional,
774            final Function<JsonNumber, T>   jsonTypeToJavaType,
775            final Class<T>                  returnClass
776        )
777    {
778        // Here, a 'get' request was made for a property that isn't actually listed among the
779        // properties in the provided JsonObject.  If 'isOptional' return null, otherwise throw
780
781        if (! jo.containsKey(propertyName))
782        {
783            if (isOptional) return null;
784
785            throw new JsonPropMissingException
786                (jo, propertyName, NUMBER, returnClass);
787        }
788
789        final JsonValue jv = jo.get(propertyName);
790
791        switch (jv.getValueType())
792        {
793            // This method allows for null-returns.  If Json-Null, return Java-Null.
794            case NULL: return null;
795
796            // This will throw ArithmeticException if this isn't a proper Java int
797            case NUMBER:
798
799
800                // REMEMBER: The primary reason for this class is that MEANINGFUL ERROR MESSAGES
801                //           make Json-Binding a lot easer...  "JsonArithmeticException" has just
802                //           about everything that you need to know when debugging this stuff
803
804                try
805                    { return jsonTypeToJavaType.apply((JsonNumber) jv); }
806
807                catch (ArithmeticException ae)
808                {
809                    throw new JsonArithmeticObjException
810                        (ae, jo, propertyName, NUMBER, jv, returnClass);
811                }
812
813            // The JsonObject property does not contain a JsonNumber.
814            default: throw new JsonTypeObjException
815                (jo, propertyName, NUMBER, jv, returnClass);
816        }
817    }
818
819
820    // ********************************************************************************************
821    // ********************************************************************************************
822    // GET: USES-FLAG METHODS
823    // ********************************************************************************************
824    // ********************************************************************************************
825
826
827    /**
828     * This is an internal helper method for retrieving an element from a {@link JsonArray},
829     * and converting it to a <B STYLE='color: red;'>Java Type</B>.
830     * <EMBED CLASS=defs DATA-TYPE=number DATA-JTYPE=JsonNumber>
831     * 
832     * @param <T>           Numeric Boxed-Type, as an instance of {@code java.lang.Class}
833     * @param ja            Any instance of {@link JsonArray}
834     * @param index         A valid index into {@code 'ja'}
835     * @param FLAGS         Error-Control / Throw flag constants, defined in {@link JFlag}
836     * @param defaultValue  <EMBED CLASS='external-html' DATA-FILE-ID=COMMON_DEF_VAL>
837     * 
838     * @return On success, this method returns the converted number (of type {@code 'T'}).
839     * 
840     * @throws IndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=IOOBEX>
841     * @throws JsonArithmeticArrException <EMBED CLASS='external-html' DATA-FILE-ID=JAEX>
842     * @throws JsonNullArrException <EMBED CLASS='external-html' DATA-FILE-ID=JNAEX>
843     * @throws JsonTypeArrException <EMBED CLASS='external-html' DATA-FILE-ID=JTAEX>
844     * 
845     * @see #getInteger(JsonArray, int, int, int)
846     * @see #getLong(JsonArray, int, int, long)
847     * @see #getShort(JsonArray, int, int, short)
848     * @see #getByte(JsonArray, int, int, byte)
849     * @see #getDouble(JsonArray, int, int, double)
850     * @see #getFloat(JsonArray, int, int, float)
851     * @see ReadNumberJSON#get(JsonArray, int, int, Number)
852     * 
853     * @see RJInternal#IOOBEX(JsonArray, int, Object, int)
854     * @see RJInternal#JNAEX(JsonArray, int, Object, int, JsonValue.ValueType, Class)
855     * @see RJInternal#JTAEX(JsonArray, int, Object, int, JsonValue.ValueType, JsonValue, Class)
856     */
857    protected static <T extends java.lang.Number> T GET(
858            final JsonArray                 ja,
859            final int                       index,
860            final int                       FLAGS,
861            final T                         defaultValue,
862            final Class<T>                  returnClass,
863            final Function<JsonNumber, T>   jsonTypeToJavaType,
864            final Function<JsonNumber, T>   typeToType2
865        )
866    {
867        // When TRUE, the index provided turned out to be outside of the bounds of the array.  The
868        // IndexOutOfBounds "handler" (the method called here) will check the FLAGS, and:
869        //
870        //  1) return the defaultValue (if Requested by 'FLAGS' for IOOBEX)
871        //  2) return null (if Requested by 'FLAGS' for IOOBEX)
872        //  3) throw IndexOutOfBoundsException
873        //
874        // NOTE: It is probably a "little less efficient" to turn this into a method call,
875        //       since there are all these parameters that have to be passed, but this is
876        //       trading "readability" (less head-aches) in exchange for efficiency.
877        //
878        // This point applies to all of the "Exception Flag Handlers" used here
879
880        if (index >= ja.size()) return IOOBEX(ja, index, defaultValue, FLAGS);
881
882        final JsonValue jv = ja.get(index);
883
884        switch (jv.getValueType())
885        {
886            // When a 'NULL' (Json-Null) JsonValue is present, the JsonNullArrException 'handler'
887            // will do one of the following:
888            //
889            //  1) return the defaultValue (if Requested by 'FLAGS' for JNAEX)
890            //  2) return null (if Requested by 'FLAGS' for JNAEX)
891            //  3) throw JsonNullArrException
892
893            case NULL: return JNAEX(ja, index, defaultValue, FLAGS, NUMBER, returnClass);
894
895            case NUMBER:
896
897                // Temp Variable, Used Twice (Just a Cast)
898                final JsonNumber n = (JsonNumber) jv;
899
900                try
901                    { return jsonTypeToJavaType.apply(n); }
902
903
904                // Because
905                //
906                // 1) A method for this code would only be invoked here, and...
907                // 2) And because there would be 9 parameters to pass, 
908                // 3) the 'inline' version of "Flag Handler" is left here!
909                //
910                // NOTE: All four "JsonArithmetic Arr/Obj Exception" exception throws
911                //       are different for each of the 4 methods where they are used.
912
913                catch (ArithmeticException ae)
914                {
915                    if ((FLAGS & RETURN_NULL_ON_AEX) != 0)          return null;
916                    if ((FLAGS & RETURN_DEFVAL_ON_AEX) != 0)        return defaultValue;
917                    if ((FLAGS & RETURN_JAPPROX_ON_AEX) != 0)       return typeToType2.apply(n);
918                    if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0)      return null;
919                    if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0)    return defaultValue;
920            
921                    throw new JsonArithmeticArrException
922                        (ae, ja, index, NUMBER, jv, returnClass);
923                }
924
925
926            // The JsonValue at the specified array-index does not contain an JsonNumber.
927            // The "JsonTypeArrException Handler" will do one of these:
928            //
929            //  1) return the defaultValue (if Requested by 'FLAGS' for JTAEX)
930            //  2) return null (if Requested by 'FLAGS' for JTAEX)
931            //  3) throw JsonTypeArrException
932
933            default: return JTAEX(ja, index, defaultValue, FLAGS, NUMBER, jv, returnClass);
934        }
935    }
936
937    /**
938     * This is an internal helper method for retrieving a property from a {@link JsonObject},
939     * and converting it to a <B STYLE='color: red;'>Java Type</B>.
940     * <EMBED CLASS=defs DATA-TYPE=number DATA-JTYPE=JsonNumber>
941     * 
942     * @param jo            Any instance of {@link JsonObject}
943     * @param propertyName  Any property name contained by {@code 'jo'}
944     * @param FLAGS         Error-Control / Throw flag constants, defined in {@link JFlag}
945     * @param defaultValue  <EMBED CLASS='external-html' DATA-FILE-ID=COMMON_DEF_VAL>
946     * 
947     * @return On success, this method returns the converted number (of type {@code 'T'}).
948     * 
949     * @throws JsonPropMissingException     <EMBED CLASS='external-html' DATA-FILE-ID=JPMEX>
950     * @throws JsonArithmeticObjException   <EMBED CLASS='external-html' DATA-FILE-ID=JAEX>
951     * @throws JsonNullObjException         <EMBED CLASS='external-html' DATA-FILE-ID=JNOEX>
952     * @throws JsonTypeObjException         <EMBED CLASS='external-html' DATA-FILE-ID=JTOEX>
953     * 
954     * @see #getInteger(JsonObject, String, int, int)
955     * @see #getLong(JsonObject, String, int, long)
956     * @see #getShort(JsonObject, String, int, short)
957     * @see #getByte(JsonObject, String, int, byte)
958     * @see #getDouble(JsonObject, String, int, double)
959     * @see #getFloat(JsonObject, String, int, float)
960     * @see ReadNumberJSON#get(JsonObject, String, int, Number)
961     * 
962     * @see RJInternal#JPMEX(JsonObject, String, Object, int, JsonValue.ValueType, Class)
963     * @see RJInternal#JNOEX(JsonObject, String, Object, int, JsonValue.ValueType, Class)
964     * @see RJInternal#JTOEX(JsonObject, String, Object, int, JsonValue.ValueType, JsonValue, Class)
965     */
966    protected static <T extends java.lang.Number> T GET(
967            final JsonObject                jo,
968            final String                    propertyName,
969            final int                       FLAGS,
970            final T                         defaultValue,
971            final Class<T>                  returnClass,
972            final Function<JsonNumber, T>   jsonTypeToJavaType,
973            final Function<JsonNumber, T>   typeToType2
974        )
975    {
976        final JsonValue jv = jo.get(propertyName);
977
978
979        // When TRUE, the user-specified 'property' (named by 'propertyName') isn't actually one
980        // of the listed properties inside the JsonObject.  The JsonPropMissingException "handler"
981        // (the method called here) will check the FLAGS, and:
982        //
983        //  1) return the defaultValue (if Requested by 'FLAGS' for JPMEX)
984        //  2) return null (if Requested by 'FLAGS' for JPMEX)
985        //  3) throw JsonPropMissingException
986        //
987        // NOTE: It is probably a "little less efficient" to turn this into a method call,
988        //       since there are all these parameters that have to be passed, but this is
989        //       trading "readability" (less head-aches) in exchange for efficiency.
990        //
991        // This point applies to all of the "Exception Flag Handlers" used here
992
993        if (jv == null) return JPMEX(jo, propertyName, defaultValue, FLAGS, NUMBER, returnClass);
994
995        switch (jv.getValueType())
996        {
997            // When a 'NULL' (Json-Null) JsonValue is present, the JsonNullObjException 'handler'
998            // will do one of the following:
999            //
1000            //  1) return the defaultValue (if Requested by 'FLAGS' for JNOEX)
1001            //  2) return null (if Requested by 'FLAGS' for JNOEX)
1002            //  3) throw JsonNullArrException
1003
1004            case NULL: return JNOEX(jo, propertyName, defaultValue, FLAGS, NUMBER, returnClass);
1005
1006            case NUMBER:
1007
1008                // Temp Variable, Used Twice (Just a Cast)
1009                final JsonNumber n = (JsonNumber) jv;
1010
1011                try
1012                    { return jsonTypeToJavaType.apply(n); }
1013
1014
1015                // Because
1016                //
1017                // 1) A method for this code would only be invoked here, and...
1018                // 2) And because there would be 9 parameters to pass, 
1019                // 3) the 'inline' version of "Flag Handler" is left here!
1020                //
1021                // NOTE: All four "JsonArithmetic Arr/Obj Exception" exception throws
1022                //       are different for each of the 4 methods where they are used.
1023
1024                catch (ArithmeticException ae)
1025                {
1026                    if ((FLAGS & RETURN_NULL_ON_AEX) != 0)          return null;
1027                    if ((FLAGS & RETURN_DEFVAL_ON_AEX) != 0)        return defaultValue;
1028                    if ((FLAGS & RETURN_JAPPROX_ON_AEX) != 0)       return typeToType2.apply(n);
1029                    if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0)      return null;
1030                    if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0)    return defaultValue;
1031
1032                    throw new JsonArithmeticObjException
1033                        (ae, jo, propertyName, NUMBER, jv, returnClass);
1034                }
1035
1036
1037            // The JsonValue of 'propertyName' does not contain an JsonNumber.
1038            // The "JsonTypeObjException Handler" will do one of these:
1039            //
1040            //  1) return the defaultValue (if Requested by 'FLAGS' for JTOEX)
1041            //  2) return null (if Requested by 'FLAGS' for JTOEX)
1042            //  3) throw JsonTypeObjException
1043
1044            default: return JTOEX(jo, propertyName, defaultValue, FLAGS, NUMBER, jv, returnClass);
1045        }
1046    }
1047
1048}
1049