1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package Torello.Java.JSON;

import java.util.function.Predicate;

import java.math.BigInteger;

import javax.json.JsonNumber;
 

// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
// This class merely provides THREE LAMBDA'S / FUNCTION-POINTERS / FUNCTIONAL-INTERFACES
// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
// 
// Getting to the bottom to this "Labyrinthine" set of "Helper Classes" really isn't that difficult
// This class, yet again, is just another attempt to 1) isolate 2) localize and 3) Make Obvious a 
// few simple tricks that are utilized to make the "Main Processing Loop" - which is class 
// Class "ProcessJsonArray") efficient and consistent.
// 
// AGAIN: All Array-Processing Classes (Classes which have names beginning with 'RJArr') do their
//        Processing using the "Main Loop" of ProcessJsonArray.  This is accomplished by 
//        converting all of the Error-Checking code into a series of "Generalized Function
//        Pointers" so that all three variants:
// 
//  * RJArrIntoStream
//  * RJArrIntoConsumer
//  * RJArrIntoArray
// 
// Can operate using the Exact Same Json-Array Processing Loop - ProcessJsonArray
//
// 
// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
// Where & How this stuff is used
// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
// 
// This class provides the followig three Lambda "Test Predicates":
// 
// * Predicate<JsonNumber> isShort  -   Retrieved with Syntax: PREDICATES::shortTypePred
// * Predicate<JsonNumber> isByte   -   Retrieved with Syntax: PREDICATES::byteTypePred
// * Predicate<JsonNumber> isLong   -   Retrieved with Syntax: PREDICATES::longTypePred
// 
// These Predicates are assigned to the BASIC_TYPES Field "jsonNumWillFit"
// For the other, remaining, Numeric-Tyes: Float, Double & Integer ...
// Class "BASIC_TYPES" simply assigns 'null' to the field "jsonNumWillFit"
// This is because these three cases are handled in special & different ways.
// 
// The field "BASIC_TYPES.jsonNumWillFit" is eventually used by the class "ChooseNumberHandler"
// to help generate a Functional-Interface that can process Numeric Json-Arrays.f
// 
// If you review that class, you can see that there *ARE ALSO* Boolean Predicate-Methods for 
// testing whether or not a JsonNumber is a valid "Float" and "Integer" - however, the problem
// with including:
// 
//  * floatTypePred
//  * doubleTypePred
//  * intTypePred
// 
// Is that the process of checking whether a number is a valid Float or Double involves **ACTUALLY
// GENERATING** a float or double instance, and then checking whether it's value actually matches
// the original BigDecimal-Value from which the Float or Double was extracted.  This means, that at
// the end of such a proposed predicate, the Floating-Point Value -- IF THE EXTRACTION SUCCEEDED, 
// AND THE NUMBER FIT -- That Floating-Point Value (Int or Double) has already been computed, and 
// already exists!  
//
// This means that the Predicate & the Processor for the two need to be done simultaneously and 
// together.  There cannot be a separate Predicate & Handler for the code, because otherwise, the
// BigDecimal -> Floating-Point Conversation would be (needlessly) performed twice!
// 
// 
// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
// Which Classes Use These
// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
// 
// The class which does the "Conversion" from Method to Method-Pointer this helper is:
// * BASIC_TYPES
// 
// The class where "jsonNumWillFit" is used is inside
// * ChooseNumberHandler.choose(...) - that class only 

class PREDICATES
{
    // ********************************************************************************************
    // ********************************************************************************************
    // BigInteger Constants for the Test Predicates (directly beneath this stuff)
    // ********************************************************************************************
    // ********************************************************************************************


    private static final BigInteger LONG_MAX    = BigInteger.valueOf(Long.MAX_VALUE);
    private static final BigInteger LONG_MIN    = BigInteger.valueOf(Long.MIN_VALUE);
    private static final BigInteger SHORT_MAX   = BigInteger.valueOf(Short.MAX_VALUE);
    private static final BigInteger SHORT_MIN   = BigInteger.valueOf(Short.MIN_VALUE);
    private static final BigInteger BYTE_MAX    = BigInteger.valueOf(Byte.MAX_VALUE);
    private static final BigInteger BYTE_MIN    = BigInteger.valueOf(Byte.MIN_VALUE);


    // ********************************************************************************************
    // ********************************************************************************************
    // SIMPLE HELPER TEST-PREDICATE'S
    // ********************************************************************************************
    // ********************************************************************************************


    static boolean shortTypePred(JsonNumber jn)
    {
        if (! jn.isIntegral()) return false;

        BigInteger  bi      = jn.bigIntegerValue();
        int         signum  = bi.signum();

        return  ((signum > 0) && (bi.compareTo(SHORT_MAX) <= 0))
            ||  ((signum < 0) && (bi.compareTo(SHORT_MIN) >= 0))
            ||  (signum == 0);
    }

    static boolean byteTypePred(JsonNumber jn)
    {
        if (! jn.isIntegral()) return false;

        BigInteger  bi      = jn.bigIntegerValue();
        int         signum  = bi.signum();

        return  ((signum > 0) && (bi.compareTo(BYTE_MAX) <= 0))
            ||  ((signum < 0) && (bi.compareTo(BYTE_MIN) >= 0))
            ||  (signum == 0);
    }

    static boolean longTypePred(JsonNumber jn)
    {
        if (! jn.isIntegral()) return false;

        BigInteger  bi      = jn.bigIntegerValue();
        int         signum  = bi.signum();

        return  ((signum > 0) && (bi.compareTo(LONG_MAX) <= 0))
            ||  ((signum < 0) && (bi.compareTo(LONG_MIN) >= 0))
            ||  (signum == 0);
    }

}