001package Torello.Browser.BrowserAPI;
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.Browser.BrowserEvent;
013import Torello.Browser.JavaScriptAPI.*;
014import Torello.Browser.helper.*;
015
016import Torello.Java.Additional.*;
017import Torello.Java.JSON.*;
018
019import static Torello.Java.JSON.JFlag.*;
020
021import Torello.Java.StrCmpr;
022import Torello.JavaDoc.StaticFunctional;
023import Torello.JavaDoc.JDHeaderBackgroundImg;
024import Torello.JavaDoc.Excuse;
025
026/**
027 * <SPAN CLASS=COPIEDJDK><B><CODE>[No Description Provided by Google]</CODE></B></SPAN>
028 * 
029 * <EMBED CLASS='external-html' DATA-FILE-ID=CODE_GEN_NOTE>
030 */
031@StaticFunctional(Excused={"counter"}, Excuses={Excuse.CONFIGURATION})
032@JDHeaderBackgroundImg(EmbedTagFileID="WOOD_PLANK_NOTE")
033public class IndexedDB
034{
035    // ********************************************************************************************
036    // ********************************************************************************************
037    // Class Header Stuff
038    // ********************************************************************************************
039    // ********************************************************************************************
040
041
042    // No Pubic Constructors
043    private IndexedDB () { }
044
045    // These two Vector's are used by all the "Methods" exported by this class.  java.lang.reflect
046    // is used to generate the JSON String's.  It saves thousands of lines of Auto-Generated Code.
047    private static final Map<String, Vector<String>>    parameterNames = new HashMap<>();
048    private static final Map<String, Vector<Class<?>>>  parameterTypes = new HashMap<>();
049
050    // Some Methods do not take any parameters - for instance all the "enable()" and "disable()"
051    // I simply could not get ride of RAW-TYPES and UNCHECKED warnings... so there are now,
052    // offically, two empty-vectors.  One for String's, and the other for Classes.
053
054    private static final Vector<String>     EMPTY_VEC_STR = new Vector<>();
055    private static final Vector<Class<?>>   EMPTY_VEC_CLASS = new Vector<>();
056
057    static
058    {
059        for (Method m : IndexedDB.class.getMethods())
060        {
061            // This doesn't work!  The parameter names are all "arg0" ... "argN"
062            // It works for java.lang.reflect.Field, BUT NOT java.lang.reflect.Parameter!
063            //
064            // Vector<String> parameterNamesList = new Vector<>(); -- NOPE!
065
066            Vector<Class<?>> parameterTypesList = new Vector<>();
067        
068            for (Parameter p : m.getParameters()) parameterTypesList.add(p.getType());
069
070            parameterTypes.put(
071                m.getName(),
072                (parameterTypesList.size() > 0) ? parameterTypesList : EMPTY_VEC_CLASS
073            );
074        }
075    }
076
077    static
078    {
079        Vector<String> v = null;
080
081        v = new Vector<String>(5);
082        parameterNames.put("clearObjectStore", v);
083        Collections.addAll(v, new String[]
084        { "securityOrigin", "storageKey", "storageBucket", "databaseName", "objectStoreName", });
085
086        v = new Vector<String>(4);
087        parameterNames.put("deleteDatabase", v);
088        Collections.addAll(v, new String[]
089        { "securityOrigin", "storageKey", "storageBucket", "databaseName", });
090
091        v = new Vector<String>(6);
092        parameterNames.put("deleteObjectStoreEntries", v);
093        Collections.addAll(v, new String[]
094        { "securityOrigin", "storageKey", "storageBucket", "databaseName", "objectStoreName", "keyRange", });
095
096        parameterNames.put("disable", EMPTY_VEC_STR);
097
098        parameterNames.put("enable", EMPTY_VEC_STR);
099
100        v = new Vector<String>(9);
101        parameterNames.put("requestData", v);
102        Collections.addAll(v, new String[]
103        { "securityOrigin", "storageKey", "storageBucket", "databaseName", "objectStoreName", "indexName", "skipCount", "pageSize", "keyRange", });
104
105        v = new Vector<String>(5);
106        parameterNames.put("getMetadata", v);
107        Collections.addAll(v, new String[]
108        { "securityOrigin", "storageKey", "storageBucket", "databaseName", "objectStoreName", });
109
110        v = new Vector<String>(4);
111        parameterNames.put("requestDatabase", v);
112        Collections.addAll(v, new String[]
113        { "securityOrigin", "storageKey", "storageBucket", "databaseName", });
114
115        v = new Vector<String>(3);
116        parameterNames.put("requestDatabaseNames", v);
117        Collections.addAll(v, new String[]
118        { "securityOrigin", "storageKey", "storageBucket", });
119    }
120
121
122    // ********************************************************************************************
123    // ********************************************************************************************
124    // Types - Static Inner Classes
125    // ********************************************************************************************
126    // ********************************************************************************************
127
128    /** Database with an array of object stores. */
129    public static class DatabaseWithObjectStores
130        extends BaseType
131        implements java.io.Serializable
132    {
133        /** For Object Serialization.  java.io.Serializable */
134        protected static final long serialVersionUID = 1;
135        
136        public boolean[] optionals()
137        { return new boolean[] { false, false, false, }; }
138        
139        /** Database name. */
140        public final String name;
141        
142        /**
143         * Database version (type is not 'integer', as the standard
144         * requires the version number to be 'unsigned long long')
145         */
146        public final Number version;
147        
148        /** Object stores in this database. */
149        public final IndexedDB.ObjectStore[] objectStores;
150        
151        /**
152         * Constructor
153         *
154         * @param name Database name.
155         * 
156         * @param version 
157         * Database version (type is not 'integer', as the standard
158         * requires the version number to be 'unsigned long long')
159         * 
160         * @param objectStores Object stores in this database.
161         */
162        public DatabaseWithObjectStores
163            (String name, Number version, IndexedDB.ObjectStore[] objectStores)
164        {
165            // Exception-Check(s) to ensure that if any parameters which are not declared as
166            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
167            
168            if (name == null)         THROWS.throwNPE("name");
169            if (version == null)      THROWS.throwNPE("version");
170            if (objectStores == null) THROWS.throwNPE("objectStores");
171            
172            this.name          = name;
173            this.version       = version;
174            this.objectStores  = objectStores;
175        }
176        
177        /**
178         * JSON Object Constructor
179         * @param jo A Json-Object having data about an instance of {@code 'DatabaseWithObjectStores'}.
180         */
181        public DatabaseWithObjectStores (JsonObject jo)
182        {
183            this.name          = ReadJSON.getString(jo, "name", false, true);
184            this.version       = ReadNumberJSON.get(jo, "version", false, true);
185            this.objectStores = (jo.getJsonArray("objectStores") == null)
186                ? null
187                : RJArrIntoStream.objArr(jo.getJsonArray("objectStores"), null, 0, IndexedDB.ObjectStore.class).toArray(IndexedDB.ObjectStore[]::new);
188        
189        }
190        
191        
192        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
193        public boolean equals(Object other)
194        {
195            if (this == other)                       return true;
196            if (other == null)                       return false;
197            if (other.getClass() != this.getClass()) return false;
198        
199            DatabaseWithObjectStores o = (DatabaseWithObjectStores) other;
200        
201            return
202                    Objects.equals(this.name, o.name)
203                &&  Objects.equals(this.version, o.version)
204                &&  Arrays.deepEquals(this.objectStores, o.objectStores);
205        }
206        
207        /** Generates a Hash-Code for {@code 'this'} instance */
208        public int hashCode()
209        {
210            return
211                    Objects.hashCode(this.name)
212                +   Objects.hashCode(this.version)
213                +   Arrays.deepHashCode(this.objectStores);
214        }
215    }
216    
217    /** Object store. */
218    public static class ObjectStore
219        extends BaseType
220        implements java.io.Serializable
221    {
222        /** For Object Serialization.  java.io.Serializable */
223        protected static final long serialVersionUID = 1;
224        
225        public boolean[] optionals()
226        { return new boolean[] { false, false, false, false, }; }
227        
228        /** Object store name. */
229        public final String name;
230        
231        /** Object store key path. */
232        public final IndexedDB.KeyPath keyPath;
233        
234        /** If true, object store has auto increment flag set. */
235        public final boolean autoIncrement;
236        
237        /** Indexes in this object store. */
238        public final IndexedDB.ObjectStoreIndex[] indexes;
239        
240        /**
241         * Constructor
242         *
243         * @param name Object store name.
244         * 
245         * @param keyPath Object store key path.
246         * 
247         * @param autoIncrement If true, object store has auto increment flag set.
248         * 
249         * @param indexes Indexes in this object store.
250         */
251        public ObjectStore(
252                String name, IndexedDB.KeyPath keyPath, boolean autoIncrement, 
253                IndexedDB.ObjectStoreIndex[] indexes
254            )
255        {
256            // Exception-Check(s) to ensure that if any parameters which are not declared as
257            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
258            
259            if (name == null)    THROWS.throwNPE("name");
260            if (keyPath == null) THROWS.throwNPE("keyPath");
261            if (indexes == null) THROWS.throwNPE("indexes");
262            
263            this.name           = name;
264            this.keyPath        = keyPath;
265            this.autoIncrement  = autoIncrement;
266            this.indexes        = indexes;
267        }
268        
269        /**
270         * JSON Object Constructor
271         * @param jo A Json-Object having data about an instance of {@code 'ObjectStore'}.
272         */
273        public ObjectStore (JsonObject jo)
274        {
275            this.name           = ReadJSON.getString(jo, "name", false, true);
276            this.keyPath        = ReadJSON.getObject(jo, "keyPath", IndexedDB.KeyPath.class, false, true);
277            this.autoIncrement  = ReadPrimJSON.getBoolean(jo, "autoIncrement");
278            this.indexes = (jo.getJsonArray("indexes") == null)
279                ? null
280                : RJArrIntoStream.objArr(jo.getJsonArray("indexes"), null, 0, IndexedDB.ObjectStoreIndex.class).toArray(IndexedDB.ObjectStoreIndex[]::new);
281        
282        }
283        
284        
285        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
286        public boolean equals(Object other)
287        {
288            if (this == other)                       return true;
289            if (other == null)                       return false;
290            if (other.getClass() != this.getClass()) return false;
291        
292            ObjectStore o = (ObjectStore) other;
293        
294            return
295                    Objects.equals(this.name, o.name)
296                &&  Objects.equals(this.keyPath, o.keyPath)
297                &&  (this.autoIncrement == o.autoIncrement)
298                &&  Arrays.deepEquals(this.indexes, o.indexes);
299        }
300        
301        /** Generates a Hash-Code for {@code 'this'} instance */
302        public int hashCode()
303        {
304            return
305                    Objects.hashCode(this.name)
306                +   this.keyPath.hashCode()
307                +   (this.autoIncrement ? 1 : 0)
308                +   Arrays.deepHashCode(this.indexes);
309        }
310    }
311    
312    /** Object store index. */
313    public static class ObjectStoreIndex
314        extends BaseType
315        implements java.io.Serializable
316    {
317        /** For Object Serialization.  java.io.Serializable */
318        protected static final long serialVersionUID = 1;
319        
320        public boolean[] optionals()
321        { return new boolean[] { false, false, false, false, }; }
322        
323        /** Index name. */
324        public final String name;
325        
326        /** Index key path. */
327        public final IndexedDB.KeyPath keyPath;
328        
329        /** If true, index is unique. */
330        public final boolean unique;
331        
332        /** If true, index allows multiple entries for a key. */
333        public final boolean multiEntry;
334        
335        /**
336         * Constructor
337         *
338         * @param name Index name.
339         * 
340         * @param keyPath Index key path.
341         * 
342         * @param unique If true, index is unique.
343         * 
344         * @param multiEntry If true, index allows multiple entries for a key.
345         */
346        public ObjectStoreIndex
347            (String name, IndexedDB.KeyPath keyPath, boolean unique, boolean multiEntry)
348        {
349            // Exception-Check(s) to ensure that if any parameters which are not declared as
350            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
351            
352            if (name == null)    THROWS.throwNPE("name");
353            if (keyPath == null) THROWS.throwNPE("keyPath");
354            
355            this.name        = name;
356            this.keyPath     = keyPath;
357            this.unique      = unique;
358            this.multiEntry  = multiEntry;
359        }
360        
361        /**
362         * JSON Object Constructor
363         * @param jo A Json-Object having data about an instance of {@code 'ObjectStoreIndex'}.
364         */
365        public ObjectStoreIndex (JsonObject jo)
366        {
367            this.name        = ReadJSON.getString(jo, "name", false, true);
368            this.keyPath     = ReadJSON.getObject(jo, "keyPath", IndexedDB.KeyPath.class, false, true);
369            this.unique      = ReadPrimJSON.getBoolean(jo, "unique");
370            this.multiEntry  = ReadPrimJSON.getBoolean(jo, "multiEntry");
371        }
372        
373        
374        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
375        public boolean equals(Object other)
376        {
377            if (this == other)                       return true;
378            if (other == null)                       return false;
379            if (other.getClass() != this.getClass()) return false;
380        
381            ObjectStoreIndex o = (ObjectStoreIndex) other;
382        
383            return
384                    Objects.equals(this.name, o.name)
385                &&  Objects.equals(this.keyPath, o.keyPath)
386                &&  (this.unique == o.unique)
387                &&  (this.multiEntry == o.multiEntry);
388        }
389        
390        /** Generates a Hash-Code for {@code 'this'} instance */
391        public int hashCode()
392        {
393            return
394                    Objects.hashCode(this.name)
395                +   this.keyPath.hashCode()
396                +   (this.unique ? 1 : 0)
397                +   (this.multiEntry ? 1 : 0);
398        }
399    }
400    
401    /** Key. */
402    public static class Key
403        extends BaseType
404        implements java.io.Serializable
405    {
406        /** For Object Serialization.  java.io.Serializable */
407        protected static final long serialVersionUID = 1;
408        
409        public boolean[] optionals()
410        { return new boolean[] { false, true, true, true, true, }; }
411        
412        /** Key type. */
413        public final String type;
414        
415        /**
416         * Number value.
417         * <BR /><B CLASS=Opt>OPTIONAL</B>
418         */
419        public final Number number;
420        
421        /**
422         * String value.
423         * <BR /><B CLASS=Opt>OPTIONAL</B>
424         */
425        public final String string;
426        
427        /**
428         * Date value.
429         * <BR /><B CLASS=Opt>OPTIONAL</B>
430         */
431        public final Number date;
432        
433        /**
434         * Array value.
435         * <BR /><B CLASS=Opt>OPTIONAL</B>
436         */
437        public final IndexedDB.Key[] array;
438        
439        /**
440         * Constructor
441         *
442         * @param type Key type.
443         * <BR />Acceptable Values: ["number", "string", "date", "array"]
444         * 
445         * @param number Number value.
446         * <BR /><B CLASS=Opt>OPTIONAL</B>
447         * 
448         * @param string String value.
449         * <BR /><B CLASS=Opt>OPTIONAL</B>
450         * 
451         * @param date Date value.
452         * <BR /><B CLASS=Opt>OPTIONAL</B>
453         * 
454         * @param array Array value.
455         * <BR /><B CLASS=Opt>OPTIONAL</B>
456         */
457        public Key
458            (String type, Number number, String string, Number date, IndexedDB.Key[] array)
459        {
460            // Exception-Check(s) to ensure that if any parameters which are not declared as
461            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
462            
463            if (type == null) THROWS.throwNPE("type");
464            
465            // Exception-Check(s) to ensure that if any parameters which must adhere to a
466            // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
467            
468            THROWS.checkIAE(
469                "type", type,
470                "number", "string", "date", "array"
471            );
472            
473            this.type    = type;
474            this.number  = number;
475            this.string  = string;
476            this.date    = date;
477            this.array   = array;
478        }
479        
480        /**
481         * JSON Object Constructor
482         * @param jo A Json-Object having data about an instance of {@code 'Key'}.
483         */
484        public Key (JsonObject jo)
485        {
486            this.type    = ReadJSON.getString(jo, "type", false, true);
487            this.number  = ReadNumberJSON.get(jo, "number", true, false);
488            this.string  = ReadJSON.getString(jo, "string", true, false);
489            this.date    = ReadNumberJSON.get(jo, "date", true, false);
490            this.array = (jo.getJsonArray("array") == null)
491                ? null
492                : RJArrIntoStream.objArr(jo.getJsonArray("array"), null, 0, IndexedDB.Key.class).toArray(IndexedDB.Key[]::new);
493        
494        }
495        
496        
497        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
498        public boolean equals(Object other)
499        {
500            if (this == other)                       return true;
501            if (other == null)                       return false;
502            if (other.getClass() != this.getClass()) return false;
503        
504            Key o = (Key) other;
505        
506            return
507                    Objects.equals(this.type, o.type)
508                &&  Objects.equals(this.number, o.number)
509                &&  Objects.equals(this.string, o.string)
510                &&  Objects.equals(this.date, o.date)
511                &&  Arrays.deepEquals(this.array, o.array);
512        }
513        
514        /** Generates a Hash-Code for {@code 'this'} instance */
515        public int hashCode()
516        {
517            return
518                    Objects.hashCode(this.type)
519                +   Objects.hashCode(this.number)
520                +   Objects.hashCode(this.string)
521                +   Objects.hashCode(this.date)
522                +   Arrays.deepHashCode(this.array);
523        }
524    }
525    
526    /** Key range. */
527    public static class KeyRange
528        extends BaseType
529        implements java.io.Serializable
530    {
531        /** For Object Serialization.  java.io.Serializable */
532        protected static final long serialVersionUID = 1;
533        
534        public boolean[] optionals()
535        { return new boolean[] { true, true, false, false, }; }
536        
537        /**
538         * Lower bound.
539         * <BR /><B CLASS=Opt>OPTIONAL</B>
540         */
541        public final IndexedDB.Key lower;
542        
543        /**
544         * Upper bound.
545         * <BR /><B CLASS=Opt>OPTIONAL</B>
546         */
547        public final IndexedDB.Key upper;
548        
549        /** If true lower bound is open. */
550        public final boolean lowerOpen;
551        
552        /** If true upper bound is open. */
553        public final boolean upperOpen;
554        
555        /**
556         * Constructor
557         *
558         * @param lower Lower bound.
559         * <BR /><B CLASS=Opt>OPTIONAL</B>
560         * 
561         * @param upper Upper bound.
562         * <BR /><B CLASS=Opt>OPTIONAL</B>
563         * 
564         * @param lowerOpen If true lower bound is open.
565         * 
566         * @param upperOpen If true upper bound is open.
567         */
568        public KeyRange
569            (IndexedDB.Key lower, IndexedDB.Key upper, boolean lowerOpen, boolean upperOpen)
570        {
571            this.lower      = lower;
572            this.upper      = upper;
573            this.lowerOpen  = lowerOpen;
574            this.upperOpen  = upperOpen;
575        }
576        
577        /**
578         * JSON Object Constructor
579         * @param jo A Json-Object having data about an instance of {@code 'KeyRange'}.
580         */
581        public KeyRange (JsonObject jo)
582        {
583            this.lower      = ReadJSON.getObject(jo, "lower", IndexedDB.Key.class, true, false);
584            this.upper      = ReadJSON.getObject(jo, "upper", IndexedDB.Key.class, true, false);
585            this.lowerOpen  = ReadPrimJSON.getBoolean(jo, "lowerOpen");
586            this.upperOpen  = ReadPrimJSON.getBoolean(jo, "upperOpen");
587        }
588        
589        
590        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
591        public boolean equals(Object other)
592        {
593            if (this == other)                       return true;
594            if (other == null)                       return false;
595            if (other.getClass() != this.getClass()) return false;
596        
597            KeyRange o = (KeyRange) other;
598        
599            return
600                    Objects.equals(this.lower, o.lower)
601                &&  Objects.equals(this.upper, o.upper)
602                &&  (this.lowerOpen == o.lowerOpen)
603                &&  (this.upperOpen == o.upperOpen);
604        }
605        
606        /** Generates a Hash-Code for {@code 'this'} instance */
607        public int hashCode()
608        {
609            return
610                    this.lower.hashCode()
611                +   this.upper.hashCode()
612                +   (this.lowerOpen ? 1 : 0)
613                +   (this.upperOpen ? 1 : 0);
614        }
615    }
616    
617    /** Data entry. */
618    public static class DataEntry
619        extends BaseType
620        implements java.io.Serializable
621    {
622        /** For Object Serialization.  java.io.Serializable */
623        protected static final long serialVersionUID = 1;
624        
625        public boolean[] optionals()
626        { return new boolean[] { false, false, false, }; }
627        
628        /** Key object. */
629        public final RunTime.RemoteObject key;
630        
631        /** Primary key object. */
632        public final RunTime.RemoteObject primaryKey;
633        
634        /** Value object. */
635        public final RunTime.RemoteObject value;
636        
637        /**
638         * Constructor
639         *
640         * @param key Key object.
641         * 
642         * @param primaryKey Primary key object.
643         * 
644         * @param value Value object.
645         */
646        public DataEntry
647            (RunTime.RemoteObject key, RunTime.RemoteObject primaryKey, RunTime.RemoteObject value)
648        {
649            // Exception-Check(s) to ensure that if any parameters which are not declared as
650            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
651            
652            if (key == null)        THROWS.throwNPE("key");
653            if (primaryKey == null) THROWS.throwNPE("primaryKey");
654            if (value == null)      THROWS.throwNPE("value");
655            
656            this.key         = key;
657            this.primaryKey  = primaryKey;
658            this.value       = value;
659        }
660        
661        /**
662         * JSON Object Constructor
663         * @param jo A Json-Object having data about an instance of {@code 'DataEntry'}.
664         */
665        public DataEntry (JsonObject jo)
666        {
667            this.key         = ReadJSON.getObject(jo, "key", RunTime.RemoteObject.class, false, true);
668            this.primaryKey  = ReadJSON.getObject(jo, "primaryKey", RunTime.RemoteObject.class, false, true);
669            this.value       = ReadJSON.getObject(jo, "value", RunTime.RemoteObject.class, false, true);
670        }
671        
672        
673        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
674        public boolean equals(Object other)
675        {
676            if (this == other)                       return true;
677            if (other == null)                       return false;
678            if (other.getClass() != this.getClass()) return false;
679        
680            DataEntry o = (DataEntry) other;
681        
682            return
683                    Objects.equals(this.key, o.key)
684                &&  Objects.equals(this.primaryKey, o.primaryKey)
685                &&  Objects.equals(this.value, o.value);
686        }
687        
688        /** Generates a Hash-Code for {@code 'this'} instance */
689        public int hashCode()
690        {
691            return
692                    this.key.hashCode()
693                +   this.primaryKey.hashCode()
694                +   this.value.hashCode();
695        }
696    }
697    
698    /** Key path. */
699    public static class KeyPath
700        extends BaseType
701        implements java.io.Serializable
702    {
703        /** For Object Serialization.  java.io.Serializable */
704        protected static final long serialVersionUID = 1;
705        
706        public boolean[] optionals()
707        { return new boolean[] { false, true, true, }; }
708        
709        /** Key path type. */
710        public final String type;
711        
712        /**
713         * String value.
714         * <BR /><B CLASS=Opt>OPTIONAL</B>
715         */
716        public final String string;
717        
718        /**
719         * Array value.
720         * <BR /><B CLASS=Opt>OPTIONAL</B>
721         */
722        public final String[] array;
723        
724        /**
725         * Constructor
726         *
727         * @param type Key path type.
728         * <BR />Acceptable Values: ["null", "string", "array"]
729         * 
730         * @param string String value.
731         * <BR /><B CLASS=Opt>OPTIONAL</B>
732         * 
733         * @param array Array value.
734         * <BR /><B CLASS=Opt>OPTIONAL</B>
735         */
736        public KeyPath(String type, String string, String[] array)
737        {
738            // Exception-Check(s) to ensure that if any parameters which are not declared as
739            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
740            
741            if (type == null) THROWS.throwNPE("type");
742            
743            // Exception-Check(s) to ensure that if any parameters which must adhere to a
744            // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
745            
746            THROWS.checkIAE(
747                "type", type,
748                "null", "string", "array"
749            );
750            
751            this.type    = type;
752            this.string  = string;
753            this.array   = array;
754        }
755        
756        /**
757         * JSON Object Constructor
758         * @param jo A Json-Object having data about an instance of {@code 'KeyPath'}.
759         */
760        public KeyPath (JsonObject jo)
761        {
762            this.type    = ReadJSON.getString(jo, "type", false, true);
763            this.string  = ReadJSON.getString(jo, "string", true, false);
764            this.array = (jo.getJsonArray("array") == null)
765                ? null
766                : RJArrIntoStream.strArr(jo.getJsonArray("array"), null, 0).toArray(String[]::new);
767        
768        }
769        
770        
771        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
772        public boolean equals(Object other)
773        {
774            if (this == other)                       return true;
775            if (other == null)                       return false;
776            if (other.getClass() != this.getClass()) return false;
777        
778            KeyPath o = (KeyPath) other;
779        
780            return
781                    Objects.equals(this.type, o.type)
782                &&  Objects.equals(this.string, o.string)
783                &&  Arrays.deepEquals(this.array, o.array);
784        }
785        
786        /** Generates a Hash-Code for {@code 'this'} instance */
787        public int hashCode()
788        {
789            return
790                    Objects.hashCode(this.type)
791                +   Objects.hashCode(this.string)
792                +   Arrays.deepHashCode(this.array);
793        }
794    }
795    
796    
797    // Counter for keeping the WebSocket Request ID's distinct.
798    private static int counter = 1;
799    
800    /**
801     * Clears all entries from an object store.
802     * 
803     * @param securityOrigin 
804     * At least and at most one of securityOrigin, storageKey, or storageBucket must be specified.
805     * Security origin.
806     * <BR /><B CLASS=Opt>OPTIONAL</B>
807     * 
808     * @param storageKey Storage key.
809     * <BR /><B CLASS=Opt>OPTIONAL</B>
810     * 
811     * @param storageBucket Storage bucket. If not specified, it uses the default bucket.
812     * <BR /><B CLASS=Opt>OPTIONAL</B>
813     * 
814     * @param databaseName Database name.
815     * 
816     * @param objectStoreName Object store name.
817     * 
818     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
819     * {@link Ret0}&gt;</CODE>
820     *
821     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
822     * browser receives the invocation-request.
823     *
824     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
825     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
826     * {@code >} to ensure the Browser Function has run to completion.
827     */
828    public static Script<String, JsonObject, Ret0> clearObjectStore(
829            String securityOrigin, String storageKey, Storage.StorageBucket storageBucket, 
830            String databaseName, String objectStoreName
831        )
832    {
833        // Exception-Check(s) to ensure that if any parameters which are not declared as
834        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
835        
836        if (databaseName == null)    THROWS.throwNPE("databaseName");
837        if (objectStoreName == null) THROWS.throwNPE("objectStoreName");
838        
839        final int       webSocketID = 27000000 + counter++;
840        final boolean[] optionals   = { true, true, true, false, false, };
841        
842        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
843        String requestJSON = WriteJSON.get(
844            parameterTypes.get("clearObjectStore"),
845            parameterNames.get("clearObjectStore"),
846            optionals, webSocketID,
847            "IndexedDB.clearObjectStore",
848            securityOrigin, storageKey, storageBucket, databaseName, objectStoreName
849        );
850        
851        // This Remote Command does not have a Return-Value.
852        return new Script<>
853            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
854    }
855    
856    /**
857     * Deletes a database.
858     * 
859     * @param securityOrigin 
860     * At least and at most one of securityOrigin, storageKey, or storageBucket must be specified.
861     * Security origin.
862     * <BR /><B CLASS=Opt>OPTIONAL</B>
863     * 
864     * @param storageKey Storage key.
865     * <BR /><B CLASS=Opt>OPTIONAL</B>
866     * 
867     * @param storageBucket Storage bucket. If not specified, it uses the default bucket.
868     * <BR /><B CLASS=Opt>OPTIONAL</B>
869     * 
870     * @param databaseName Database name.
871     * 
872     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
873     * {@link Ret0}&gt;</CODE>
874     *
875     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
876     * browser receives the invocation-request.
877     *
878     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
879     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
880     * {@code >} to ensure the Browser Function has run to completion.
881     */
882    public static Script<String, JsonObject, Ret0> deleteDatabase(
883            String securityOrigin, String storageKey, Storage.StorageBucket storageBucket, 
884            String databaseName
885        )
886    {
887        // Exception-Check(s) to ensure that if any parameters which are not declared as
888        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
889        
890        if (databaseName == null) THROWS.throwNPE("databaseName");
891        
892        final int       webSocketID = 27001000 + counter++;
893        final boolean[] optionals   = { true, true, true, false, };
894        
895        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
896        String requestJSON = WriteJSON.get(
897            parameterTypes.get("deleteDatabase"),
898            parameterNames.get("deleteDatabase"),
899            optionals, webSocketID,
900            "IndexedDB.deleteDatabase",
901            securityOrigin, storageKey, storageBucket, databaseName
902        );
903        
904        // This Remote Command does not have a Return-Value.
905        return new Script<>
906            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
907    }
908    
909    /**
910     * Delete a range of entries from an object store
911     * 
912     * @param securityOrigin 
913     * At least and at most one of securityOrigin, storageKey, or storageBucket must be specified.
914     * Security origin.
915     * <BR /><B CLASS=Opt>OPTIONAL</B>
916     * 
917     * @param storageKey Storage key.
918     * <BR /><B CLASS=Opt>OPTIONAL</B>
919     * 
920     * @param storageBucket Storage bucket. If not specified, it uses the default bucket.
921     * <BR /><B CLASS=Opt>OPTIONAL</B>
922     * 
923     * @param databaseName -
924     * 
925     * @param objectStoreName -
926     * 
927     * @param keyRange Range of entry keys to delete
928     * 
929     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
930     * {@link Ret0}&gt;</CODE>
931     *
932     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
933     * browser receives the invocation-request.
934     *
935     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
936     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
937     * {@code >} to ensure the Browser Function has run to completion.
938     */
939    public static Script<String, JsonObject, Ret0> deleteObjectStoreEntries(
940            String securityOrigin, String storageKey, Storage.StorageBucket storageBucket, 
941            String databaseName, String objectStoreName, IndexedDB.KeyRange keyRange
942        )
943    {
944        // Exception-Check(s) to ensure that if any parameters which are not declared as
945        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
946        
947        if (databaseName == null)    THROWS.throwNPE("databaseName");
948        if (objectStoreName == null) THROWS.throwNPE("objectStoreName");
949        if (keyRange == null)        THROWS.throwNPE("keyRange");
950        
951        final int       webSocketID = 27002000 + counter++;
952        final boolean[] optionals   = { true, true, true, false, false, false, };
953        
954        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
955        String requestJSON = WriteJSON.get(
956            parameterTypes.get("deleteObjectStoreEntries"),
957            parameterNames.get("deleteObjectStoreEntries"),
958            optionals, webSocketID,
959            "IndexedDB.deleteObjectStoreEntries",
960            securityOrigin, storageKey, storageBucket, databaseName, objectStoreName, keyRange
961        );
962        
963        // This Remote Command does not have a Return-Value.
964        return new Script<>
965            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
966    }
967    
968    /**
969     * Disables events from backend.
970     * 
971     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
972     * {@link Ret0}&gt;</CODE>
973     *
974     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
975     * browser receives the invocation-request.
976     *
977     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
978     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
979     * {@code >} to ensure the Browser Function has run to completion.
980     */
981    public static Script<String, JsonObject, Ret0> disable()
982    {
983        final int          webSocketID = 27003000 + counter++;
984        final boolean[]    optionals   = new boolean[0];
985        
986        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
987        String requestJSON = WriteJSON.get(
988            parameterTypes.get("disable"),
989            parameterNames.get("disable"),
990            optionals, webSocketID,
991            "IndexedDB.disable"
992        );
993        
994        // This Remote Command does not have a Return-Value.
995        return new Script<>
996            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
997    }
998    
999    /**
1000     * Enables events from backend.
1001     * 
1002     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
1003     * {@link Ret0}&gt;</CODE>
1004     *
1005     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
1006     * browser receives the invocation-request.
1007     *
1008     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
1009     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
1010     * {@code >} to ensure the Browser Function has run to completion.
1011     */
1012    public static Script<String, JsonObject, Ret0> enable()
1013    {
1014        final int          webSocketID = 27004000 + counter++;
1015        final boolean[]    optionals   = new boolean[0];
1016        
1017        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
1018        String requestJSON = WriteJSON.get(
1019            parameterTypes.get("enable"),
1020            parameterNames.get("enable"),
1021            optionals, webSocketID,
1022            "IndexedDB.enable"
1023        );
1024        
1025        // This Remote Command does not have a Return-Value.
1026        return new Script<>
1027            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
1028    }
1029    
1030    /**
1031     * Requests data from object store or index.
1032     * 
1033     * @param securityOrigin 
1034     * At least and at most one of securityOrigin, storageKey, or storageBucket must be specified.
1035     * Security origin.
1036     * <BR /><B CLASS=Opt>OPTIONAL</B>
1037     * 
1038     * @param storageKey Storage key.
1039     * <BR /><B CLASS=Opt>OPTIONAL</B>
1040     * 
1041     * @param storageBucket Storage bucket. If not specified, it uses the default bucket.
1042     * <BR /><B CLASS=Opt>OPTIONAL</B>
1043     * 
1044     * @param databaseName Database name.
1045     * 
1046     * @param objectStoreName Object store name.
1047     * 
1048     * @param indexName Index name, empty string for object store data requests.
1049     * 
1050     * @param skipCount Number of records to skip.
1051     * 
1052     * @param pageSize Number of records to fetch.
1053     * 
1054     * @param keyRange Key range.
1055     * <BR /><B CLASS=Opt>OPTIONAL</B>
1056     * 
1057     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
1058     * {@link Ret2}&gt;</CODE>
1059     *
1060     * <BR /><BR />This {@link Script} may be <B STYLE='color:red'>executed</B> (using 
1061     * {@link Script#exec()}), and a {@link Promise} returned.
1062     *
1063     * <BR /><BR />When the {@code Promise} is <B STYLE='color: red'>awaited</B>
1064     * (using {@link Promise#await()}), the {@code Ret2} will subsequently
1065     * be returned from that call.
1066     * 
1067     * <BR /><BR />The <B STYLE='color: red'>returned</B> values are encapsulated
1068     * in an instance of <B>{@link Ret2}</B>
1069     *
1070     * <BR /><BR /><UL CLASS=JDUL>
1071     * <LI><CODE><B>Ret2.a:</B> {@link IndexedDB.DataEntry}[] (<B>objectStoreDataEntries</B>)</CODE>
1072     *     <BR />Array of object store data entries.
1073     *     <BR /><BR /></LI>
1074     * <LI><CODE><B>Ret2.b:</B> Boolean (<B>hasMore</B>)</CODE>
1075     *     <BR />If true, there are more entries to fetch in the given range.
1076     *     </LI>
1077     * </UL>
1078     */
1079    public static Script<String, JsonObject, Ret2<IndexedDB.DataEntry[], Boolean>> requestData(
1080            String securityOrigin, String storageKey, Storage.StorageBucket storageBucket, 
1081            String databaseName, String objectStoreName, String indexName, int skipCount, 
1082            int pageSize, IndexedDB.KeyRange keyRange
1083        )
1084    {
1085        // Exception-Check(s) to ensure that if any parameters which are not declared as
1086        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
1087        
1088        if (databaseName == null)    THROWS.throwNPE("databaseName");
1089        if (objectStoreName == null) THROWS.throwNPE("objectStoreName");
1090        if (indexName == null)       THROWS.throwNPE("indexName");
1091        
1092        final int       webSocketID = 27005000 + counter++;
1093        final boolean[] optionals   = { true, true, true, false, false, false, false, false, true, };
1094        
1095        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
1096        String requestJSON = WriteJSON.get(
1097            parameterTypes.get("requestData"),
1098            parameterNames.get("requestData"),
1099            optionals, webSocketID,
1100            "IndexedDB.requestData",
1101            securityOrigin, storageKey, storageBucket, databaseName, objectStoreName, indexName,
1102            skipCount, pageSize, keyRange
1103        );
1104        
1105        // 'JSON Binding' ... Converts Browser Response-JSON into Java-Type 'Ret2'
1106        Function<JsonObject, Ret2<IndexedDB.DataEntry[], Boolean>>
1107            responseProcessor = (JsonObject jo) -> new Ret2<>(
1108                (jo.getJsonArray("objectStoreDataEntries") == null)
1109                    ? null
1110                    : RJArrIntoStream.objArr(jo.getJsonArray("objectStoreDataEntries"), null, 0, IndexedDB.DataEntry.class).toArray(IndexedDB.DataEntry[]::new),
1111                ReadBoxedJSON.getBoolean(jo, "hasMore", true)
1112            );
1113        
1114        return new Script<>(webSocketID, requestJSON, responseProcessor);
1115    }
1116    
1117    /**
1118     * Gets metadata of an object store.
1119     * 
1120     * @param securityOrigin 
1121     * At least and at most one of securityOrigin, storageKey, or storageBucket must be specified.
1122     * Security origin.
1123     * <BR /><B CLASS=Opt>OPTIONAL</B>
1124     * 
1125     * @param storageKey Storage key.
1126     * <BR /><B CLASS=Opt>OPTIONAL</B>
1127     * 
1128     * @param storageBucket Storage bucket. If not specified, it uses the default bucket.
1129     * <BR /><B CLASS=Opt>OPTIONAL</B>
1130     * 
1131     * @param databaseName Database name.
1132     * 
1133     * @param objectStoreName Object store name.
1134     * 
1135     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
1136     * {@link Ret2}&gt;</CODE>
1137     *
1138     * <BR /><BR />This {@link Script} may be <B STYLE='color:red'>executed</B> (using 
1139     * {@link Script#exec()}), and a {@link Promise} returned.
1140     *
1141     * <BR /><BR />When the {@code Promise} is <B STYLE='color: red'>awaited</B>
1142     * (using {@link Promise#await()}), the {@code Ret2} will subsequently
1143     * be returned from that call.
1144     * 
1145     * <BR /><BR />The <B STYLE='color: red'>returned</B> values are encapsulated
1146     * in an instance of <B>{@link Ret2}</B>
1147     *
1148     * <BR /><BR /><UL CLASS=JDUL>
1149     * <LI><CODE><B>Ret2.a:</B> Number (<B>entriesCount</B>)</CODE>
1150     *     <BR />the entries count
1151     *     <BR /><BR /></LI>
1152     * <LI><CODE><B>Ret2.b:</B> Number (<B>keyGeneratorValue</B>)</CODE>
1153     *     <BR />the current value of key generator, to become the next inserted
1154     *     key into the object store. Valid if objectStore.autoIncrement
1155     *     is true.
1156     *     </LI>
1157     * </UL>
1158     */
1159    public static Script<String, JsonObject, Ret2<Number, Number>> getMetadata(
1160            String securityOrigin, String storageKey, Storage.StorageBucket storageBucket, 
1161            String databaseName, String objectStoreName
1162        )
1163    {
1164        // Exception-Check(s) to ensure that if any parameters which are not declared as
1165        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
1166        
1167        if (databaseName == null)    THROWS.throwNPE("databaseName");
1168        if (objectStoreName == null) THROWS.throwNPE("objectStoreName");
1169        
1170        final int       webSocketID = 27006000 + counter++;
1171        final boolean[] optionals   = { true, true, true, false, false, };
1172        
1173        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
1174        String requestJSON = WriteJSON.get(
1175            parameterTypes.get("getMetadata"),
1176            parameterNames.get("getMetadata"),
1177            optionals, webSocketID,
1178            "IndexedDB.getMetadata",
1179            securityOrigin, storageKey, storageBucket, databaseName, objectStoreName
1180        );
1181        
1182        // 'JSON Binding' ... Converts Browser Response-JSON into Java-Type 'Ret2'
1183        Function<JsonObject, Ret2<Number, Number>>
1184            responseProcessor = (JsonObject jo) -> new Ret2<>(
1185                ReadNumberJSON.get(jo, "entriesCount", false, true),
1186                ReadNumberJSON.get(jo, "keyGeneratorValue", false, true)
1187            );
1188        
1189        return new Script<>(webSocketID, requestJSON, responseProcessor);
1190    }
1191    
1192    /**
1193     * Requests database with given name in given frame.
1194     * 
1195     * @param securityOrigin 
1196     * At least and at most one of securityOrigin, storageKey, or storageBucket must be specified.
1197     * Security origin.
1198     * <BR /><B CLASS=Opt>OPTIONAL</B>
1199     * 
1200     * @param storageKey Storage key.
1201     * <BR /><B CLASS=Opt>OPTIONAL</B>
1202     * 
1203     * @param storageBucket Storage bucket. If not specified, it uses the default bucket.
1204     * <BR /><B CLASS=Opt>OPTIONAL</B>
1205     * 
1206     * @param databaseName Database name.
1207     * 
1208     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
1209     * {@link IndexedDB.DatabaseWithObjectStores}&gt;</CODE>
1210     * 
1211     * <BR /><BR />This <B>script</B> may be <B STYLE='color: red'>executed</B>, using
1212     * {@link Script#exec()}, and afterwards, a {@link Promise}<CODE>&lt;JsonObject,
1213     * {@link IndexedDB.DatabaseWithObjectStores}&gt;</CODE> will be returned.
1214     *
1215     * <BR /><BR />Finally, the <B>{@code Promise}</B> may be <B STYLE='color: red'>awaited</B>,
1216     * using {@link Promise#await()}, <I>and the returned result of this Browser Function may
1217      * may be retrieved.</I>
1218     *
1219     * <BR /><BR />This Browser Function <B STYLE='color: red'>returns</B>
1220     * <BR /><BR /><UL CLASS=JDUL>
1221     * <LI><CODE>{@link IndexedDB.DatabaseWithObjectStores} (<B>databaseWithObjectStores</B></CODE>)
1222     *     <BR />Database with an array of object stores.
1223     * </LI>
1224     * </UL> */
1225    public static Script<String, JsonObject, IndexedDB.DatabaseWithObjectStores> requestDatabase(
1226            String securityOrigin, String storageKey, Storage.StorageBucket storageBucket, 
1227            String databaseName
1228        )
1229    {
1230        // Exception-Check(s) to ensure that if any parameters which are not declared as
1231        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
1232        
1233        if (databaseName == null) THROWS.throwNPE("databaseName");
1234        
1235        final int       webSocketID = 27007000 + counter++;
1236        final boolean[] optionals   = { true, true, true, false, };
1237        
1238        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
1239        String requestJSON = WriteJSON.get(
1240            parameterTypes.get("requestDatabase"),
1241            parameterNames.get("requestDatabase"),
1242            optionals, webSocketID,
1243            "IndexedDB.requestDatabase",
1244            securityOrigin, storageKey, storageBucket, databaseName
1245        );
1246        
1247        // 'JSON Binding' ... Converts Browser Response-JSON to 'IndexedDB.DatabaseWithObjectStores'
1248        Function<JsonObject, IndexedDB.DatabaseWithObjectStores> responseProcessor = (JsonObject jo) ->
1249            ReadJSON.getObject(jo, "databaseWithObjectStores", IndexedDB.DatabaseWithObjectStores.class, false, true);
1250        
1251        return new Script<>(webSocketID, requestJSON, responseProcessor);
1252    }
1253    
1254    /**
1255     * Requests database names for given security origin.
1256     * 
1257     * @param securityOrigin 
1258     * At least and at most one of securityOrigin, storageKey, or storageBucket must be specified.
1259     * Security origin.
1260     * <BR /><B CLASS=Opt>OPTIONAL</B>
1261     * 
1262     * @param storageKey Storage key.
1263     * <BR /><B CLASS=Opt>OPTIONAL</B>
1264     * 
1265     * @param storageBucket Storage bucket. If not specified, it uses the default bucket.
1266     * <BR /><B CLASS=Opt>OPTIONAL</B>
1267     * 
1268     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
1269     * String[]&gt;</CODE>
1270     * 
1271     * <BR /><BR />This <B>script</B> may be <B STYLE='color: red'>executed</B>, using
1272     * {@link Script#exec()}, and afterwards, a {@link Promise}<CODE>&lt;JsonObject,
1273     * String[]&gt;</CODE> will be returned.
1274     *
1275     * <BR /><BR />Finally, the <B>{@code Promise}</B> may be <B STYLE='color: red'>awaited</B>,
1276     * using {@link Promise#await()}, <I>and the returned result of this Browser Function may
1277      * may be retrieved.</I>
1278     *
1279     * <BR /><BR />This Browser Function <B STYLE='color: red'>returns</B>
1280     * <BR /><BR /><UL CLASS=JDUL>
1281     * <LI><CODE>String[] (<B>databaseNames</B></CODE>)
1282     *     <BR />Database names for origin.
1283     * </LI>
1284     * </UL> */
1285    public static Script<String, JsonObject, String[]> requestDatabaseNames
1286        (String securityOrigin, String storageKey, Storage.StorageBucket storageBucket)
1287    {
1288        final int       webSocketID = 27008000 + counter++;
1289        final boolean[] optionals   = { true, true, true, };
1290        
1291        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
1292        String requestJSON = WriteJSON.get(
1293            parameterTypes.get("requestDatabaseNames"),
1294            parameterNames.get("requestDatabaseNames"),
1295            optionals, webSocketID,
1296            "IndexedDB.requestDatabaseNames",
1297            securityOrigin, storageKey, storageBucket
1298        );
1299        
1300        // 'JSON Binding' ... Converts Browser Response-JSON to 'String[]'
1301        Function<JsonObject, String[]> responseProcessor = (JsonObject jo) ->
1302            (jo.getJsonArray("databaseNames") == null)
1303                ? null
1304                : RJArrIntoStream.strArr(jo.getJsonArray("databaseNames"), null, 0).toArray(String[]::new);
1305        
1306        return new Script<>(webSocketID, requestJSON, responseProcessor);
1307    }
1308    
1309}