001package Torello.Browser;
002
003import java.math.BigInteger;
004import java.math.BigDecimal;
005
006import javax.json.stream.JsonGenerator;
007
008/**
009 * Yes, this is a great name for a class.
010 * 
011 * <BR /><BR />
012 * This class can capable write all variety of numbers, and arrays of numbers to a provided
013 * {@link JsonGenerator} instance, no more no less.
014 * 
015 * <BR /><BR /><DIV CLASS=JDHint>
016 * 💡 Java's (somewhat) standardized "Glass Fish" implementation is great, but is a little
017 * "unfinished".
018 * </DIV>
019 */
020@Torello.JavaDoc.Annotations.StaticFunctional
021@Torello.JavaDoc.Annotations.JDHeaderBackgroundImg(EmbedTagFileID="INTERNAL_USE_JDHBI")
022public class NumberCrap
023{
024    private NumberCrap() { }
025
026    /**
027     * Writes a number to an output {@link JsonGenerator}.
028     * 
029     * @param jGen      The output Json stream used to properly format Json into a string
030     * @param paramName The Json property name for the number being written to the output
031     * 
032     * @param paramValue Any one of the valid, supported types.
033     * <BR />👉 Please review the hilited code below, in order to view which types are supported
034     * 
035     * @throws InvalidNumberTypeError
036     * <EMBED CLASS='external-html' DATA-FILE-ID=NumberCrap.InvalidNumberTypeError>
037     */
038    public static void handleNumber(
039            final JsonGenerator jGen,
040            final String        paramName,
041            final Number        paramValue
042        )
043    {
044        if (paramValue == null) throw new InvalidNumberTypeError
045            ("Parameter 'paramValue' was passed null.  This should be a valid java.lang.Number");
046
047        if (paramName != null) switch (paramValue.getClass().getSimpleName())
048        {
049            case "Integer" :    jGen.write(paramName, ((Integer) paramValue).intValue());   break;
050            case "Long" :       jGen.write(paramName, ((Long) paramValue).longValue());     break;
051
052            case "Float" :      jGen.write(paramName, ((Float) paramValue).floatValue());   break;
053            case "Double" :     jGen.write(paramName, ((Double) paramValue).doubleValue()); break;
054
055            case "BigInteger" : jGen.write(paramName, ((BigInteger) paramValue)); break;
056            case "BigDecimal" : jGen.write(paramName, ((BigDecimal) paramValue)); break;
057
058            default : throw new InvalidNumberTypeError(
059                "Parameter 'paramValue' has an invalid Number-Type: " +
060                paramValue.getClass().getCanonicalName() + '\n'
061            );
062        }
063
064        else switch (paramValue.getClass().getSimpleName())
065        {
066            case "Integer" :    jGen.write(((Integer) paramValue).intValue());   break;
067            case "Long" :       jGen.write(((Long) paramValue).longValue());     break;
068
069            case "Float" :      jGen.write(((Float) paramValue).floatValue());   break;
070            case "Double" :     jGen.write(((Double) paramValue).doubleValue()); break;
071
072            case "BigInteger" : jGen.write(((BigInteger) paramValue)); break;
073            case "BigDecimal" : jGen.write(((BigDecimal) paramValue)); break;
074
075            default : throw new InvalidNumberTypeError(
076                "Parameter 'paramValue' has an invalid Number-Type: " +
077                paramValue.getClass().getCanonicalName() + '\n'
078            );
079        }
080    }
081
082    /**
083     * Writes a numeric array to an output {@link JsonGenerator}.
084     * 
085     * @param jGen      The output Json stream used to properly format Json into a string
086     * @param paramName The Json property name for the number being written to the output
087     * 
088     * @param paramValue An array having one of the pre-selected types.
089     * <BR />👉 Please review the hilited code below, in order to view which types are supported
090     * 
091     * @throws InvalidNumberTypeError
092     * <EMBED CLASS='external-html' DATA-FILE-ID=NumberCrap.InvalidNumberTypeError>
093     */
094    public static void handleNumberArr(
095            final JsonGenerator jGen,
096            final String        paramName,
097            final Object        paramValue
098        )
099    {
100        if (paramValue == null) throw new InvalidNumberTypeError(
101            "Parameter 'paramValue' was passed null.  This should be a valid, one dimensional " +
102            "array of numbers"
103        );
104
105        if (paramName == null)  jGen.writeStartArray();
106        else                    jGen.writeStartArray(paramName);
107
108        final String typeAsStr = paramValue.getClass().getSimpleName();
109
110        switch (typeAsStr)
111        {
112            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
113            // primitive arrays
114            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
115
116            case "int[]" :
117                for (final int i : (int[]) paramValue) jGen.write(i);
118                break;
119
120            case "long[]" :
121                for  (final long l : (long[]) paramValue) jGen.write(l);
122                break;
123
124            case "float[]" :
125                for (final float f : (float[]) paramValue) jGen.write(f);
126                break;
127
128            case "double[]" :
129                for (final double d : (double[]) paramValue) jGen.write(d);
130                break;
131
132
133            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
134            // boxed arrays
135            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
136
137            case "Integer[]" :
138                for (final Integer i : (Integer[]) paramValue)
139                    if (i == null)  jGen.writeNull();
140                    else            jGen.write(i.intValue());
141                break;
142
143            case "Long[]" :
144                for (final Long l : (Long[]) paramValue)
145                    if (l == null)  jGen.writeNull();
146                    else            jGen.write(l.longValue());
147                break;
148
149            case "Float[]" :
150                for (final Float f : (Float[]) paramValue)
151                    if (f == null)  jGen.writeNull();
152                    else            jGen.write(f.floatValue());
153                break;
154
155            case "Double[]" :
156                for (final Double d : (Double[]) paramValue)
157                    if (d == null)  jGen.writeNull();
158                    else            jGen.write(d.doubleValue());
159                break;
160
161            case "Number[]" :
162                for (final Number n : (Number[]) paramValue)
163                    if (n == null)  jGen.writeNull();
164                    else            handleNumber(jGen, null, n);
165                break;
166
167
168            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
169            // Other
170            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
171
172            default :
173
174                if (typeAsStr.endsWith("[]"))
175                    throw new InvalidNumberTypeError(
176                        "Input array-parameter 'paramValue' has an invalid class / type: " +
177                        paramValue.getClass().getCanonicalName() + '\n' +
178                        "This should be a one-dimensional array of numbers.  Please see this " +
179                        "class' source code for the complete list of valid array types."
180                    );
181
182                else throw new InvalidNumberTypeError(
183                    "Input array-parameter 'paramValue' isn't actually a one-dimensional array: " +
184                    paramValue.getClass().getCanonicalName() + '\n'
185                );
186        }
187        jGen.writeEnd();
188    }
189
190    /**
191     * Writes any numeric array having any concrete implementation of the abstract Java Type
192     * {@code java.lang.Number} to an output {@link JsonGenerator}.
193     * 
194     * @param jGen      The output Json stream used to properly format Json into a string
195     * @param paramName The Json property name for the number being written to the output
196     * 
197     * @param paramValue Any two-dimensional array of numbers having one of the pre-selected types
198     * <BR />👉 Please review the hilited code below, in order to view which types are supported
199     * 
200     * @throws InvalidNumberTypeError
201     * <EMBED CLASS='external-html' DATA-FILE-ID=NumberCrap.InvalidNumberTypeError>
202     */
203    public static void handleNumberArr2D(JsonGenerator jGen, String paramName, Object paramValue)
204    {
205        if (paramValue == null) throw new InvalidNumberTypeError(
206            "Parameter 'paramValue' was passed null.  This should be a valid, two dimensional " +
207            "array of numbers"
208        );
209
210        jGen.writeStartArray(paramName);
211
212        final String typeAsStr = paramValue.getClass().getSimpleName();
213
214        switch (paramValue.getClass().getSimpleName())
215        {
216            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
217            // primitive arrays
218            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
219
220            case "int[][]" :
221                for (final int[] iArr : (int[][]) paramValue)
222                {
223                    jGen.writeStartArray();
224                    for (final int i : iArr) jGen.write(i);
225                    jGen.writeEnd();
226                }
227                break;
228
229            case "long[][]" :
230                for  (final long[] lArr : (long[][]) paramValue)
231                {
232                    jGen.writeStartArray();
233                    for (final long l : lArr) jGen.write(l);
234                    jGen.writeEnd();
235                }
236                break;
237
238            case "float[][]" :
239                for (final float[] fArr : (float[][]) paramValue)
240                {
241                    jGen.writeStartArray();
242                    for (final float f : fArr) jGen.write(f);
243                    jGen.writeEnd();
244                }
245                break;
246
247            case "double[][]" :
248                for (final double[] dArr : (double[][]) paramValue)
249                {
250                    jGen.writeStartArray();
251                    for (final double d : dArr) jGen.write(d);
252                    jGen.writeEnd();
253                }
254                break;
255
256
257            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
258            // boxed arrays
259            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
260            
261            case "Integer[][]" :
262                for (final Integer[] iArr : (Integer[][]) paramValue)
263                    if (iArr == null) jGen.writeNull();
264                    else
265                    {
266                        jGen.writeStartArray();
267                        for (final Integer i : iArr)
268                            if (i == null)  jGen.writeNull();
269                            else            jGen.write(i.intValue());
270                        jGen.writeEnd();
271                    }
272                break;
273
274            case "Long[][]" :
275                for (final Long[] lArr : (Long[][]) paramValue)
276                    if (lArr == null) jGen.writeNull();
277                    else
278                    {
279                        jGen.writeStartArray();
280                        for (final Long l : lArr)
281                            if (l == null)  jGen.writeNull();
282                            else            jGen.write(l.longValue());
283                        jGen.writeEnd();
284                    }
285                break;
286
287            case "Float[][]" :
288                for (final Float[] fArr : (Float[][]) paramValue)
289                    if (fArr == null) jGen.writeNull();
290                    else
291                    {
292                        jGen.writeStartArray();
293                        for (final Float f : fArr)
294                            if (f == null)  jGen.writeNull();
295                            else            jGen.write(f.floatValue());
296                        jGen.writeEnd();
297                    }
298                break;
299
300            case "Double[][]" :
301                for (final Double[] dArr : (Double[][]) paramValue)
302                    if (dArr == null) jGen.writeNull();
303                    else
304                    {
305                        jGen.writeStartArray();
306                        for (final Double d : dArr)
307                            if (d == null)  jGen.writeNull();
308                            else            jGen.write(d.doubleValue());
309                        jGen.writeEnd();
310                    }
311                break;
312
313            case "Number[][]" :
314                for (final Number[] nArr : (Number[][]) paramValue)
315                    if (nArr == null)   jGen.writeNull();
316                    else                handleNumberArr(jGen, null, nArr);
317                break;
318
319
320            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
321            // Other
322            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
323
324            default :
325
326                if (typeAsStr.endsWith("[]")) throw new InvalidNumberTypeError(
327                    "Input array-parameter 'paramValue' has an invalid class / type: " +
328                    paramValue.getClass().getCanonicalName() + '\n' +
329                    "This should be a two-dimensional array of numbers.  Please see this " +
330                    "class' source code for the complete list of valid array types."
331                );
332
333                else throw new InvalidNumberTypeError(
334                    "Input array-parameter 'paramValue' isn't actually a two-dimensional array: " +
335                    '[' + typeAsStr + ']'
336                );
337        }
338
339        jGen.writeEnd();
340    }
341
342}