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}