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><CODE>[No Description Provided by Google]</CODE></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 Database
030{
031    // ********************************************************************************************
032    // ********************************************************************************************
033    // Class Header Stuff
034    // ********************************************************************************************
035    // ********************************************************************************************
036
037
038    // No Pubic Constructors
039    private Database () { }
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 : Database.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("disable", EMPTY_VEC_STR);
078
079        parameterNames.put("enable", EMPTY_VEC_STR);
080
081        v = new Vector<String>(2);
082        parameterNames.put("executeSQL", v);
083        Collections.addAll(v, new String[]
084        { "databaseId", "query", });
085
086        v = new Vector<String>(1);
087        parameterNames.put("getDatabaseTableNames", v);
088        Collections.addAll(v, new String[]
089        { "databaseId", });
090    }
091
092
093    // ********************************************************************************************
094    // ********************************************************************************************
095    // Types - Static Inner Classes
096    // ********************************************************************************************
097    // ********************************************************************************************
098
099    // public static class DatabaseId => String
100    
101    /** Database object. */
102    public static class _Database
103        extends BaseType
104        implements java.io.Serializable
105    {
106        /** For Object Serialization.  java.io.Serializable */
107        protected static final long serialVersionUID = 1;
108        
109        public boolean[] optionals()
110        { return new boolean[] { false, false, false, false, }; }
111        
112        /** Database ID. */
113        public final String id;
114        
115        /** Database domain. */
116        public final String domain;
117        
118        /** Database name. */
119        public final String name;
120        
121        /** Database version. */
122        public final String version;
123        
124        /**
125         * Constructor
126         *
127         * @param id Database ID.
128         * 
129         * @param domain Database domain.
130         * 
131         * @param name Database name.
132         * 
133         * @param version Database version.
134         */
135        public _Database(String id, String domain, String name, String version)
136        {
137            // Exception-Check(s) to ensure that if any parameters which are not declared as
138            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
139            
140            if (id == null)      BRDPC.throwNPE("id");
141            if (domain == null)  BRDPC.throwNPE("domain");
142            if (name == null)    BRDPC.throwNPE("name");
143            if (version == null) BRDPC.throwNPE("version");
144            
145            this.id       = id;
146            this.domain   = domain;
147            this.name     = name;
148            this.version  = version;
149        }
150        
151        /**
152         * JSON Object Constructor
153         * @param jo A Json-Object having data about an instance of {@code 'Database'}.
154         */
155        public _Database (JsonObject jo)
156        {
157            this.id       = ReadJSON.getString(jo, "id", false, true);
158            this.domain   = ReadJSON.getString(jo, "domain", false, true);
159            this.name     = ReadJSON.getString(jo, "name", false, true);
160            this.version  = ReadJSON.getString(jo, "version", false, true);
161        }
162        
163        
164        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
165        public boolean equals(Object other)
166        {
167            if (other == null)                       return false;
168            if (other.getClass() != this.getClass()) return false;
169        
170            _Database o = (_Database) other;
171        
172            return
173                    Objects.equals(this.id, o.id)
174                &&  Objects.equals(this.domain, o.domain)
175                &&  Objects.equals(this.name, o.name)
176                &&  Objects.equals(this.version, o.version);
177        }
178        
179        /** Generates a Hash-Code for {@code 'this'} instance */
180        public int hashCode()
181        {
182            return
183                    Objects.hashCode(this.id)
184                +   Objects.hashCode(this.domain)
185                +   Objects.hashCode(this.name)
186                +   Objects.hashCode(this.version);
187        }
188    }
189    
190    /** Database error. */
191    public static class Error
192        extends BaseType
193        implements java.io.Serializable
194    {
195        /** For Object Serialization.  java.io.Serializable */
196        protected static final long serialVersionUID = 1;
197        
198        public boolean[] optionals()
199        { return new boolean[] { false, false, }; }
200        
201        /** Error message. */
202        public final String message;
203        
204        /** Error code. */
205        public final int code;
206        
207        /**
208         * Constructor
209         *
210         * @param message Error message.
211         * 
212         * @param code Error code.
213         */
214        public Error(String message, int code)
215        {
216            // Exception-Check(s) to ensure that if any parameters which are not declared as
217            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
218            
219            if (message == null) BRDPC.throwNPE("message");
220            
221            this.message  = message;
222            this.code     = code;
223        }
224        
225        /**
226         * JSON Object Constructor
227         * @param jo A Json-Object having data about an instance of {@code 'Error'}.
228         */
229        public Error (JsonObject jo)
230        {
231            this.message  = ReadJSON.getString(jo, "message", false, true);
232            this.code     = ReadPrimJSON.getInt(jo, "code");
233        }
234        
235        
236        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
237        public boolean equals(Object other)
238        {
239            if (other == null)                       return false;
240            if (other.getClass() != this.getClass()) return false;
241        
242            Error o = (Error) other;
243        
244            return
245                    Objects.equals(this.message, o.message)
246                &&  (this.code == o.code);
247        }
248        
249        /** Generates a Hash-Code for {@code 'this'} instance */
250        public int hashCode()
251        {
252            return
253                    Objects.hashCode(this.message)
254                +   this.code;
255        }
256    }
257    
258    /** <CODE>[No Description Provided by Google]</CODE> */
259    public static class addDatabase
260        extends BrowserEvent
261        implements java.io.Serializable
262    {
263        /** For Object Serialization.  java.io.Serializable */
264        protected static final long serialVersionUID = 1;
265        
266        public boolean[] optionals()
267        { return new boolean[] { false, }; }
268        
269        /** <CODE>[No Description Provided by Google]</CODE> */
270        public final Database._Database database;
271        
272        /**
273         * Constructor
274         *
275         * @param database -
276         */
277        public addDatabase(Database._Database database)
278        {
279            super("Database", "addDatabase", 1);
280            
281            // Exception-Check(s) to ensure that if any parameters which are not declared as
282            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
283            
284            if (database == null) BRDPC.throwNPE("database");
285            
286            this.database  = database;
287        }
288        
289        /**
290         * JSON Object Constructor
291         * @param jo A Json-Object having data about an instance of {@code 'addDatabase'}.
292         */
293        public addDatabase (JsonObject jo)
294        {
295            super("Database", "addDatabase", 1);
296        
297            this.database  = ReadJSON.getObject(jo, "database", Database._Database.class, false, true);
298        }
299        
300        
301        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
302        public boolean equals(Object other)
303        {
304            if (other == null)                       return false;
305            if (other.getClass() != this.getClass()) return false;
306        
307            addDatabase o = (addDatabase) other;
308        
309            return
310                    Objects.equals(this.database, o.database);
311        }
312        
313        /** Generates a Hash-Code for {@code 'this'} instance */
314        public int hashCode()
315        {
316            return
317                    this.database.hashCode();
318        }
319    }
320    
321    
322    // Counter for keeping the WebSocket Request ID's distinct.
323    private static int counter = 1;
324    
325    /**
326     * Disables database tracking, prevents database events from being sent to the client.
327     * 
328     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
329     * {@link Ret0}&gt;</CODE>
330     *
331     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
332     * browser receives the invocation-request.
333     *
334     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
335     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
336     * {@code >} to ensure the Browser Function has run to completion.
337     */
338    public static Script<String, JsonObject, Ret0> disable()
339    {
340        final int          webSocketID = 19000000 + counter++;
341        final boolean[]    optionals   = new boolean[0];
342        
343        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
344        String requestJSON = WriteJSON.get(
345            parameterTypes.get("disable"),
346            parameterNames.get("disable"),
347            optionals, webSocketID,
348            "Database.disable"
349        );
350        
351        // This Remote Command does not have a Return-Value.
352        return new Script<>
353            (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues);
354    }
355    
356    /**
357     * Enables database tracking, database events will now be delivered to the client.
358     * 
359     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
360     * {@link Ret0}&gt;</CODE>
361     *
362     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
363     * browser receives the invocation-request.
364     *
365     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
366     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
367     * {@code >} to ensure the Browser Function has run to completion.
368     */
369    public static Script<String, JsonObject, Ret0> enable()
370    {
371        final int          webSocketID = 19001000 + counter++;
372        final boolean[]    optionals   = new boolean[0];
373        
374        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
375        String requestJSON = WriteJSON.get(
376            parameterTypes.get("enable"),
377            parameterNames.get("enable"),
378            optionals, webSocketID,
379            "Database.enable"
380        );
381        
382        // This Remote Command does not have a Return-Value.
383        return new Script<>
384            (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues);
385    }
386    
387    /**
388     * <CODE>[No Description Provided by Google]</CODE>
389     * 
390     * @param databaseId -
391     * 
392     * @param query -
393     * 
394     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
395     * {@link Ret3}&gt;</CODE>
396     *
397     * <BR /><BR />This {@link Script} may be <B STYLE='color:red'>executed</B> (using 
398     * {@link Script#exec()}), and a {@link Promise} returned.
399     *
400     * <BR /><BR />When the {@code Promise} is <B STYLE='color: red'>awaited</B>
401     * (using {@link Promise#await()}), the {@code Ret3} will subsequently
402     * be returned from that call.
403     * 
404     * <BR /><BR />The <B STYLE='color: red'>returned</B> values are encapsulated
405     * in an instance of <B>{@link Ret3}</B>
406     *
407     * <BR /><BR /><UL CLASS=JDUL>
408     * <LI><CODE><B>Ret3.a:</B> String[] (<B>columnNames</B>)</CODE>
409     *     <BR />-
410     *     <BR /><BR /></LI>
411     * <LI><CODE><B>Ret3.b:</B> JsonArray (<B>values</B>)</CODE>
412     *     <BR />-
413     *     <BR /><BR /></LI>
414     * <LI><CODE><B>Ret3.c:</B> {@link Database.Error} (<B>sqlError</B>)</CODE>
415     *     <BR />-
416     *     </LI>
417     * </UL>
418     */
419    public static Script<String, JsonObject, Ret3<String[], JsonArray, Database.Error>> executeSQL
420        (String databaseId, String query)
421    {
422        // Exception-Check(s) to ensure that if any parameters which are not declared as
423        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
424        
425        if (databaseId == null) BRDPC.throwNPE("databaseId");
426        if (query == null)      BRDPC.throwNPE("query");
427        
428        final int       webSocketID = 19002000 + counter++;
429        final boolean[] optionals   = { false, false, };
430        
431        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
432        String requestJSON = WriteJSON.get(
433            parameterTypes.get("executeSQL"),
434            parameterNames.get("executeSQL"),
435            optionals, webSocketID,
436            "Database.executeSQL",
437            databaseId, query
438        );
439        
440        // 'JSON Binding' ... Converts Browser Response-JSON into Java-Type 'Ret3'
441        Function<JsonObject, Ret3<String[], JsonArray, Database.Error>> 
442            responseProcessor = (JsonObject jo) -> new Ret3<>(
443                (jo.getJsonArray("columnNames") == null)
444                    ? null
445                    : ReadArrJSON.DimN.strArr(jo.getJsonArray("columnNames"), null, 0, String[].class),
446                jo.getJsonArray("values"),
447                ReadJSON.getObject(jo, "sqlError", Database.Error.class, true, false)
448            );
449        
450        // Pass the 'defaultSender' to Script-Constructor
451        // The sender that is used can be changed before executing script.
452        return new Script<>(BRDPC.defaultSender, webSocketID, requestJSON, responseProcessor);
453    }
454    
455    /**
456     * <CODE>[No Description Provided by Google]</CODE>
457     * 
458     * @param databaseId -
459     * 
460     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
461     * String[]&gt;</CODE>
462     * 
463     * <BR /><BR />This <B>script</B> may be <B STYLE='color: red'>executed</B>, using
464     * {@link Script#exec()}, and afterwards, a {@link Promise}<CODE>&lt;JsonObject,
465     * String[]&gt;</CODE> will be returned.
466     *
467     * <BR /><BR />Finally, the <B>{@code Promise}</B> may be <B STYLE='color: red'>awaited</B>,
468     * using {@link Promise#await()}, <I>and the returned result of this Browser Function may
469      * may be retrieved.</I>
470     *
471     * <BR /><BR />This Browser Function <B STYLE='color: red'>returns</B>
472     * <BR /><BR /><UL CLASS=JDUL>
473     * <LI><CODE>String[] (<B>tableNames</B></CODE>)
474     *     <BR />-
475     * </LI>
476     * </UL> */
477    public static Script<String, JsonObject, String[]> getDatabaseTableNames(String databaseId)
478    {
479        // Exception-Check(s) to ensure that if any parameters which are not declared as
480        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
481        
482        if (databaseId == null) BRDPC.throwNPE("databaseId");
483        
484        final int       webSocketID = 19003000 + counter++;
485        final boolean[] optionals   = { false, };
486        
487        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
488        String requestJSON = WriteJSON.get(
489            parameterTypes.get("getDatabaseTableNames"),
490            parameterNames.get("getDatabaseTableNames"),
491            optionals, webSocketID,
492            "Database.getDatabaseTableNames",
493            databaseId
494        );
495        
496        // 'JSON Binding' ... Converts Browser Response-JSON to 'String[]'
497        Function<JsonObject, String[]> responseProcessor = (JsonObject jo) ->
498            (jo.getJsonArray("tableNames") == null)
499                ? null
500                : ReadArrJSON.DimN.strArr(jo.getJsonArray("tableNames"), null, 0, String[].class);
501        
502        // Pass the 'defaultSender' to Script-Constructor
503        // The sender that is used can be changed before executing script.
504        return new Script<>(BRDPC.defaultSender, webSocketID, requestJSON, responseProcessor);
505    }
506    
507}