001package Torello.Browser;
002
003import java.util.*;
004import javax.json.*;
005import javax.json.stream.*;
006import java.io.*;
007
008import java.lang.reflect.Method;
009import java.lang.reflect.Parameter;
010import java.util.function.Function;
011
012import Torello.Java.Additional.*;
013import Torello.Java.JSON.*;
014
015import static Torello.Java.JSON.JFlag.*;
016
017import Torello.Java.StrCmpr;
018import Torello.JavaDoc.StaticFunctional;
019import Torello.JavaDoc.JDHeaderBackgroundImg;
020import Torello.JavaDoc.Excuse;
021
022/**
023 * <SPAN CLASS=COPIEDJDK><B>This domain is deprecated.</B></SPAN>
024 * 
025 * <EMBED CLASS='external-html' DATA-FILE-ID=CODE_GEN_NOTE>
026 */
027@StaticFunctional(Excused={"counter"}, Excuses={Excuse.CONFIGURATION})
028@JDHeaderBackgroundImg(EmbedTagFileID="WOOD_PLANK_NOTE")
029public class Schema
030{
031    // ********************************************************************************************
032    // ********************************************************************************************
033    // Class Header Stuff
034    // ********************************************************************************************
035    // ********************************************************************************************
036
037
038    // No Pubic Constructors
039    private Schema () { }
040
041    // These two Vector's are used by all the "Methods" exported by this class.  java.lang.reflect
042    // is used to generate the JSON String's.  It saves thousands of lines of Auto-Generated Code.
043    private static final Map<String, Vector<String>>    parameterNames = new HashMap<>();
044    private static final Map<String, Vector<Class<?>>>  parameterTypes = new HashMap<>();
045
046    // Some Methods do not take any parameters - for instance all the "enable()" and "disable()"
047    // I simply could not get ride of RAW-TYPES and UNCHECKED warnings... so there are now,
048    // offically, two empty-vectors.  One for String's, and the other for Classes.
049
050    private static final Vector<String>     EMPTY_VEC_STR = new Vector<>();
051    private static final Vector<Class<?>>   EMPTY_VEC_CLASS = new Vector<>();
052
053    static
054    {
055        for (Method m : Schema.class.getMethods())
056        {
057            // This doesn't work!  The parameter names are all "arg0" ... "argN"
058            // It works for java.lang.reflect.Field, BUT NOT java.lang.reflect.Parameter!
059            //
060            // Vector<String> parameterNamesList = new Vector<>(); -- NOPE!
061
062            Vector<Class<?>> parameterTypesList = new Vector<>();
063        
064            for (Parameter p : m.getParameters()) parameterTypesList.add(p.getType());
065
066            parameterTypes.put(
067                m.getName(),
068                (parameterTypesList.size() > 0) ? parameterTypesList : EMPTY_VEC_CLASS
069            );
070        }
071    }
072
073    static
074    {
075        Vector<String> v = null;
076
077        parameterNames.put("getDomains", EMPTY_VEC_STR);
078    }
079
080
081    // ********************************************************************************************
082    // ********************************************************************************************
083    // Types - Static Inner Classes
084    // ********************************************************************************************
085    // ********************************************************************************************
086
087    /** Description of the protocol domain. */
088    public static class Domain
089        extends BaseType
090        implements java.io.Serializable
091    {
092        /** For Object Serialization.  java.io.Serializable */
093        protected static final long serialVersionUID = 1;
094        
095        public boolean[] optionals()
096        { return new boolean[] { false, false, }; }
097        
098        /** Domain name. */
099        public final String name;
100        
101        /** Domain version. */
102        public final String version;
103        
104        /**
105         * Constructor
106         *
107         * @param name Domain name.
108         * 
109         * @param version Domain version.
110         */
111        public Domain(String name, String version)
112        {
113            // Exception-Check(s) to ensure that if any parameters which are not declared as
114            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
115            
116            if (name == null)    BRDPC.throwNPE("name");
117            if (version == null) BRDPC.throwNPE("version");
118            
119            this.name     = name;
120            this.version  = version;
121        }
122        
123        /**
124         * JSON Object Constructor
125         * @param jo A Json-Object having data about an instance of {@code 'Domain'}.
126         */
127        public Domain (JsonObject jo)
128        {
129            this.name     = ReadJSON.getString(jo, "name", false, true);
130            this.version  = ReadJSON.getString(jo, "version", false, true);
131        }
132        
133        
134        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
135        public boolean equals(Object other)
136        {
137            if (other == null)                       return false;
138            if (other.getClass() != this.getClass()) return false;
139        
140            Domain o = (Domain) other;
141        
142            return
143                    Objects.equals(this.name, o.name)
144                &&  Objects.equals(this.version, o.version);
145        }
146        
147        /** Generates a Hash-Code for {@code 'this'} instance */
148        public int hashCode()
149        {
150            return
151                    Objects.hashCode(this.name)
152                +   Objects.hashCode(this.version);
153        }
154    }
155    
156    
157    // Counter for keeping the WebSocket Request ID's distinct.
158    private static int counter = 1;
159    
160    /**
161     * Returns supported domains.
162     * 
163     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
164     * {@link Schema.Domain}[]&gt;</CODE>
165     * 
166     * <BR /><BR />This <B>script</B> may be <B STYLE='color: red'>executed</B>, using
167     * {@link Script#exec()}, and afterwards, a {@link Promise}<CODE>&lt;JsonObject,
168     * {@link Schema.Domain}[]&gt;</CODE> will be returned.
169     *
170     * <BR /><BR />Finally, the <B>{@code Promise}</B> may be <B STYLE='color: red'>awaited</B>,
171     * using {@link Promise#await()}, <I>and the returned result of this Browser Function may
172      * may be retrieved.</I>
173     *
174     * <BR /><BR />This Browser Function <B STYLE='color: red'>returns</B>
175     * <BR /><BR /><UL CLASS=JDUL>
176     * <LI><CODE>{@link Schema.Domain}[] (<B>domains</B></CODE>)
177     *     <BR />List of supported domains.
178     * </LI>
179     * </UL> */
180    public static Script<String, JsonObject, Schema.Domain[]> getDomains()
181    {
182        final int          webSocketID = 6000000 + counter++;
183        final boolean[]    optionals   = new boolean[0];
184        
185        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
186        String requestJSON = WriteJSON.get(
187            parameterTypes.get("getDomains"),
188            parameterNames.get("getDomains"),
189            optionals, webSocketID,
190            "Schema.getDomains"
191        );
192        
193        // 'JSON Binding' ... Converts Browser Response-JSON to 'Schema.Domain[]'
194        Function<JsonObject, Schema.Domain[]> responseProcessor = (JsonObject jo) ->
195            (jo.getJsonArray("domains") == null)
196                ? null
197                : ReadArrJSON.DimN.objArr(jo.getJsonArray("domains"), null, 0, Schema.Domain[].class);
198        
199        // Pass the 'defaultSender' to Script-Constructor
200        // The sender that is used can be changed before executing script.
201        return new Script<>(BRDPC.defaultSender, webSocketID, requestJSON, responseProcessor);
202    }
203    
204}