001package Torello.JSON;
002
003import Torello.Java.Additional.Counter;
004import Torello.Java.Function.IntTFunction;
005import Torello.Java.Function.IntIntTFunc;
006
007import java.lang.reflect.Constructor;
008import java.lang.reflect.Modifier;
009
010import java.util.Objects;
011
012import java.util.function.Function;
013
014import javax.json.JsonObject;
015import javax.json.JsonException;
016
017
018// This is (sort of, but not really) "the CHEATING CLASS" 
019// Cheating is where "EXTENDED TYPES" actually extends "BASIC TYPES".
020// 
021// How can an "Extended Type" actually be an instance of "Basic Type", ask you I?
022// Well, that's how it has been implemented.  The word "extends" and "EXTENDED" are the same exact
023// word in the English Language, and that's the reason I chose not to make them a different class
024// The "SettingsRec" would have to have another constructor if I had chosen not to allow 
025// "EXTENDED_TYPES" actually not be a descendant of "BASIC_TYPES"
026//  
027// The two "Object Types" are specified by the user, and are - essentially - the exact opposite
028// of what is meant by "Basic Types".  It is for this very reason that there are no singleton
029// instances stored into this class for those configuration records. 
030
031public class EXTENDED_TYPES<T> extends BASIC_TYPES<T>
032{
033    final boolean ONE_ARG_OR_THREE_ARG;
034
035    private final Function<JsonObject, T> singleArgUserTypeBuilder;
036
037    private final IntIntTFunc<JsonObject, T> tripleArgUserTypeBuilder;
038
039    Function<JsonObject, T> singleArgUserTypeBuilder()
040    { return this.singleArgUserTypeBuilder; }
041
042    IntTFunction<JsonObject, T> tripleArgUserTypeBuilder(final ACCEPTOR<T> acceptor)
043    {
044        if (! ONE_ARG_OR_THREE_ARG) return null;
045
046        return (int jaLoopCount, JsonObject jo) ->
047
048            this.tripleArgUserTypeBuilder.apply
049                (jaLoopCount, acceptor.retrieveCount(), jo);
050
051    }
052
053    // Precisely one of these two "Object Builder" Parameter will be non-null
054    // There are two separate Static-Builders which invoke this constructor
055
056    private EXTENDED_TYPES(final Class<T> c, final Function<JsonObject, T> builder)
057    {
058        super(c);
059        this.ONE_ARG_OR_THREE_ARG       = true;
060        this.singleArgUserTypeBuilder   = builder;
061        this.tripleArgUserTypeBuilder   = null;
062    }
063
064    private EXTENDED_TYPES(final Class<T> c, final IntIntTFunc<JsonObject, T> builder)
065    {
066        super(c);
067        this.ONE_ARG_OR_THREE_ARG       = false;
068        this.singleArgUserTypeBuilder   = null;
069        this.tripleArgUserTypeBuilder   = builder;
070    }
071
072
073    // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
074    // Variant #1: Single Argument Builders ==> USE THE FIRST CONSTRUCTOR LISTED ABOVE
075    // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
076
077    static <T> BASIC_TYPES<T> FROM_CTOR(final Class<T> c)
078    {
079        final Constructor<T> ctor = InvalidClassException.check(c);
080
081        final Function<JsonObject, T> objBuilder = (JsonObject jo) ->
082        {
083            try
084                { return ctor.newInstance(jo); }
085
086            catch (Exception e)
087            {
088                throw new RuntimeException
089                    ("Failed to Build POJO\n\t" + e.getClass().getSimpleName(), e);
090            }
091        };
092
093        return new EXTENDED_TYPES<>(c, objBuilder);
094    }
095
096    static <T> BASIC_TYPES<T> ONE_ARG_FUNC(
097            final Function<JsonObject, T>   objBuilder,
098            final Class<T>                  c
099        )
100    { return new EXTENDED_TYPES<>(c, objBuilder); }
101
102
103    // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
104    // Variant #2: IntIntTFunction (Three Argument) Builders ==> USES SECOND CONSTRUCTOR, ABOVE
105    // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
106
107    static <T> BASIC_TYPES<T> THREE_ARG_FUNC(
108            final IntIntTFunc<JsonObject, T>    objBuilder,
109            final Class<T>                      c
110        )
111    { return new EXTENDED_TYPES<>(c, objBuilder); }
112}