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
package Torello.JSON;

import Torello.Java.Additional.Counter;
import Torello.Java.Function.IntTFunction;
import Torello.Java.Function.IntIntTFunc;

import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;

import java.util.Objects;

import java.util.function.Function;

import javax.json.JsonObject;
import javax.json.JsonException;


// This is (sort of, but not really) "the CHEATING CLASS" 
// Cheating is where "EXTENDED TYPES" actually extends "BASIC TYPES".
// 
// How can an "Extended Type" actually be an instance of "Basic Type", ask you I?
// Well, that's how it has been implemented.  The word "extends" and "EXTENDED" are the same exact
// word in the English Language, and that's the reason I chose not to make them a different class
// The "SettingsRec" would have to have another constructor if I had chosen not to allow 
// "EXTENDED_TYPES" actually not be a descendant of "BASIC_TYPES"
//  
// The two "Object Types" are specified by the user, and are - essentially - the exact opposite
// of what is meant by "Basic Types".  It is for this very reason that there are no singleton
// instances stored into this class for those configuration records. 

public class EXTENDED_TYPES<T> extends BASIC_TYPES<T>
{
    final boolean ONE_ARG_OR_THREE_ARG;

    private final Function<JsonObject, T> singleArgUserTypeBuilder;

    private final IntIntTFunc<JsonObject, T> tripleArgUserTypeBuilder;

    Function<JsonObject, T> singleArgUserTypeBuilder()
    { return this.singleArgUserTypeBuilder; }

    IntTFunction<JsonObject, T> tripleArgUserTypeBuilder(final ACCEPTOR<T> acceptor)
    {
        if (! ONE_ARG_OR_THREE_ARG) return null;

        return (int jaLoopCount, JsonObject jo) ->

            this.tripleArgUserTypeBuilder.apply
                (jaLoopCount, acceptor.retrieveCount(), jo);

    }

    // Precisely one of these two "Object Builder" Parameter will be non-null
    // There are two separate Static-Builders which invoke this constructor

    private EXTENDED_TYPES(final Class<T> c, final Function<JsonObject, T> builder)
    {
        super(c);
        this.ONE_ARG_OR_THREE_ARG       = true;
        this.singleArgUserTypeBuilder   = builder;
        this.tripleArgUserTypeBuilder   = null;
    }

    private EXTENDED_TYPES(final Class<T> c, final IntIntTFunc<JsonObject, T> builder)
    {
        super(c);
        this.ONE_ARG_OR_THREE_ARG       = false;
        this.singleArgUserTypeBuilder   = null;
        this.tripleArgUserTypeBuilder   = builder;
    }


    // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
    // Variant #1: Single Argument Builders ==> USE THE FIRST CONSTRUCTOR LISTED ABOVE
    // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

    static <T> BASIC_TYPES<T> FROM_CTOR(final Class<T> c)
    {
        final Constructor<T> ctor = InvalidClassException.check(c);

        final Function<JsonObject, T> objBuilder = (JsonObject jo) ->
        {
            try
                { return ctor.newInstance(jo); }

            catch (Exception e)
            {
                throw new RuntimeException
                    ("Failed to Build POJO\n\t" + e.getClass().getSimpleName(), e);
            }
        };

        return new EXTENDED_TYPES<>(c, objBuilder);
    }

    static <T> BASIC_TYPES<T> ONE_ARG_FUNC(
            final Function<JsonObject, T>   objBuilder,
            final Class<T>                  c
        )
    { return new EXTENDED_TYPES<>(c, objBuilder); }


    // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
    // Variant #2: IntIntTFunction (Three Argument) Builders ==> USES SECOND CONSTRUCTOR, ABOVE
    // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

    static <T> BASIC_TYPES<T> THREE_ARG_FUNC(
            final IntIntTFunc<JsonObject, T>    objBuilder,
            final Class<T>                      c
        )
    { return new EXTENDED_TYPES<>(c, objBuilder); }
}