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