001package Torello.Java.JSON;
002
003import Torello.Java.StringParse;
004
005import java.lang.reflect.Array;
006
007import javax.json.JsonArray;
008import javax.json.JsonValue;
009
010import static javax.json.JsonValue.ValueType.*;
011
012public class ProcessMultiDimJsonArray
013{
014    private ProcessMultiDimJsonArray() { }
015
016    @SuppressWarnings("unchecked")
017
018    /**
019     * This class is invoked by the class {@link RJArrDimN}
020     * 
021     * @param <BASIC_TYPE> The "Component Type" of the Output-Array.
022     * 
023     * @param <STREAM_TYPE> The "Intermediate Stream Type", which is present before the conversion
024     * to an Array.
025     * 
026     * @param <RETURN_ARR_TYPE> The actual Return-Type of the method.  This must be an Array-Class,
027     * such as {@code int[][].class} or (in the case of Boxed-Type Arrays) {@code Integer[][]}.
028     * 
029     * @param ja Any instance of {@link JsonArray}.  The contents sof this array should match the 
030     * dimensionality of the expected Output-Array Type, or an exception will likelyy throw.
031     * 
032     * @param rec
033     * @param retArrClass
034     * @return
035     */
036    protected static <BASIC_TYPE, STREAM_TYPE, RETURN_ARR_TYPE> RETURN_ARR_TYPE jsonArrayToJava(
037            final JsonArray                             ja,
038            final SettingsRec<BASIC_TYPE, STREAM_TYPE>  rec,
039            final Class<RETURN_ARR_TYPE>                retArrClass
040        )
041    {
042        // If this is requesting a one-dimensional array, get it using the 1D-Generator,
043        // and simply return that array.  This requires a cast because there is no way to prove
044        // to the Java-Compiler that <T> is equal to any return-value at all.
045        //
046        // Remember that this is only guaranteed (it works!) because the helper methods are all
047        // protected or private, and it has been guaranteed through rigorous testing, and
048        // preventing the user from playing with it!
049
050        if (StringParse.countCharacters(retArrClass.getSimpleName(), '[') == 1)
051            return (RETURN_ARR_TYPE) rec.array1DGenerator.apply(ja);
052
053
054        // Otherwise, this is not a single-dimension (1D) array.  Instead, the JsonArray needs
055        // to be iterated, and this method called, recursively, on each of the sub-arrays.
056        //
057        // NOTE: 'compClass' will also be an array, but with one fewer dimensions
058
059        final Class<?>          compClass   = retArrClass.getComponentType();
060        final int               SIZE        = ja.size();
061        final RETURN_ARR_TYPE   retArr      = (RETURN_ARR_TYPE) Array.newInstance(compClass, SIZE);
062
063        JsonValue jv = null;
064
065        for (int i=0; i < SIZE; i++)
066
067            switch ((jv = ja.get(i)).getValueType())
068            {
069                // javax.json.JsonValue.ValueType.NULL
070                case NULL: Array.set(retArr, i, null); break;
071
072                // javax.json.JsonValue.ValueType.ARRAY (JsonArray)
073                case ARRAY:
074
075                    Array.set(
076                        retArr,
077                        i,
078                        JSON_ARRAY_DIMN.jsonArrayToJava((JsonArray) jv, rec, compClass)
079                    );
080
081                    break;
082
083                // javax.json.JsonValue.ValueType.TRUE, FALSE, NUMBER, STRING, OBJECT
084                default:
085
086                    if (rec.IN_NSAT)        Array.set(retArr, i, null);
087                    else if (rec.S_NSAT)    continue;
088                    else throw new JsonTypeArrException(ja, i, ARRAY, jv, retArrClass);
089            }
090
091        return retArr;
092    }
093}