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 CacheStorage
034{
035    // ********************************************************************************************
036    // ********************************************************************************************
037    // Class Header Stuff
038    // ********************************************************************************************
039    // ********************************************************************************************
040
041
042    // No Pubic Constructors
043    private CacheStorage () { }
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 : CacheStorage.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>(1);
082        parameterNames.put("deleteCache", v);
083        Collections.addAll(v, new String[]
084        { "cacheId", });
085
086        v = new Vector<String>(2);
087        parameterNames.put("deleteEntry", v);
088        Collections.addAll(v, new String[]
089        { "cacheId", "request", });
090
091        v = new Vector<String>(3);
092        parameterNames.put("requestCacheNames", v);
093        Collections.addAll(v, new String[]
094        { "securityOrigin", "storageKey", "storageBucket", });
095
096        v = new Vector<String>(3);
097        parameterNames.put("requestCachedResponse", v);
098        Collections.addAll(v, new String[]
099        { "cacheId", "requestURL", "requestHeaders", });
100
101        v = new Vector<String>(4);
102        parameterNames.put("requestEntries", v);
103        Collections.addAll(v, new String[]
104        { "cacheId", "skipCount", "pageSize", "pathFilter", });
105    }
106
107
108    // ********************************************************************************************
109    // ********************************************************************************************
110    // Types - Static Inner Classes
111    // ********************************************************************************************
112    // ********************************************************************************************
113
114    // public static class CacheId => String
115    
116    /** type of HTTP response cached */
117    public static final String[] CachedResponseType =
118    { "basic", "cors", "default", "error", "opaqueResponse", "opaqueRedirect", };
119    
120    /** Data entry. */
121    public static class DataEntry
122        extends BaseType
123        implements java.io.Serializable
124    {
125        /** For Object Serialization.  java.io.Serializable */
126        protected static final long serialVersionUID = 1;
127        
128        public boolean[] optionals()
129        { return new boolean[] { false, false, false, false, false, false, false, false, }; }
130        
131        /** Request URL. */
132        public final String requestURL;
133        
134        /** Request method. */
135        public final String requestMethod;
136        
137        /** Request headers */
138        public final CacheStorage.Header[] requestHeaders;
139        
140        /** Number of seconds since epoch. */
141        public final Number responseTime;
142        
143        /** HTTP response status code. */
144        public final int responseStatus;
145        
146        /** HTTP response status text. */
147        public final String responseStatusText;
148        
149        /** HTTP response type */
150        public final String responseType;
151        
152        /** Response headers */
153        public final CacheStorage.Header[] responseHeaders;
154        
155        /**
156         * Constructor
157         *
158         * @param requestURL Request URL.
159         * 
160         * @param requestMethod Request method.
161         * 
162         * @param requestHeaders Request headers
163         * 
164         * @param responseTime Number of seconds since epoch.
165         * 
166         * @param responseStatus HTTP response status code.
167         * 
168         * @param responseStatusText HTTP response status text.
169         * 
170         * @param responseType HTTP response type
171         * 
172         * @param responseHeaders Response headers
173         */
174        public DataEntry(
175                String requestURL, String requestMethod, CacheStorage.Header[] requestHeaders, 
176                Number responseTime, int responseStatus, String responseStatusText, 
177                String responseType, CacheStorage.Header[] responseHeaders
178            )
179        {
180            // Exception-Check(s) to ensure that if any parameters which are not declared as
181            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
182            
183            if (requestURL == null)         THROWS.throwNPE("requestURL");
184            if (requestMethod == null)      THROWS.throwNPE("requestMethod");
185            if (requestHeaders == null)     THROWS.throwNPE("requestHeaders");
186            if (responseTime == null)       THROWS.throwNPE("responseTime");
187            if (responseStatusText == null) THROWS.throwNPE("responseStatusText");
188            if (responseType == null)       THROWS.throwNPE("responseType");
189            if (responseHeaders == null)    THROWS.throwNPE("responseHeaders");
190            
191            // Exception-Check(s) to ensure that if any parameters which must adhere to a
192            // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
193            
194            THROWS.checkIAE("responseType", responseType, "CacheStorage.CachedResponseType", CacheStorage.CachedResponseType);
195            
196            this.requestURL          = requestURL;
197            this.requestMethod       = requestMethod;
198            this.requestHeaders      = requestHeaders;
199            this.responseTime        = responseTime;
200            this.responseStatus      = responseStatus;
201            this.responseStatusText  = responseStatusText;
202            this.responseType        = responseType;
203            this.responseHeaders     = responseHeaders;
204        }
205        
206        /**
207         * JSON Object Constructor
208         * @param jo A Json-Object having data about an instance of {@code 'DataEntry'}.
209         */
210        public DataEntry (JsonObject jo)
211        {
212            this.requestURL          = ReadJSON.getString(jo, "requestURL", false, true);
213            this.requestMethod       = ReadJSON.getString(jo, "requestMethod", false, true);
214            this.requestHeaders = (jo.getJsonArray("requestHeaders") == null)
215                ? null
216                : RJArrIntoStream.objArr(jo.getJsonArray("requestHeaders"), null, 0, CacheStorage.Header.class).toArray(CacheStorage.Header[]::new);
217        
218            this.responseTime        = ReadNumberJSON.get(jo, "responseTime", false, true);
219            this.responseStatus      = ReadPrimJSON.getInt(jo, "responseStatus");
220            this.responseStatusText  = ReadJSON.getString(jo, "responseStatusText", false, true);
221            this.responseType        = ReadJSON.getString(jo, "responseType", false, true);
222            this.responseHeaders = (jo.getJsonArray("responseHeaders") == null)
223                ? null
224                : RJArrIntoStream.objArr(jo.getJsonArray("responseHeaders"), null, 0, CacheStorage.Header.class).toArray(CacheStorage.Header[]::new);
225        
226        }
227        
228        
229        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
230        public boolean equals(Object other)
231        {
232            if (this == other)                       return true;
233            if (other == null)                       return false;
234            if (other.getClass() != this.getClass()) return false;
235        
236            DataEntry o = (DataEntry) other;
237        
238            return
239                    Objects.equals(this.requestURL, o.requestURL)
240                &&  Objects.equals(this.requestMethod, o.requestMethod)
241                &&  Arrays.deepEquals(this.requestHeaders, o.requestHeaders)
242                &&  Objects.equals(this.responseTime, o.responseTime)
243                &&  (this.responseStatus == o.responseStatus)
244                &&  Objects.equals(this.responseStatusText, o.responseStatusText)
245                &&  Objects.equals(this.responseType, o.responseType)
246                &&  Arrays.deepEquals(this.responseHeaders, o.responseHeaders);
247        }
248        
249        /** Generates a Hash-Code for {@code 'this'} instance */
250        public int hashCode()
251        {
252            return
253                    Objects.hashCode(this.requestURL)
254                +   Objects.hashCode(this.requestMethod)
255                +   Arrays.deepHashCode(this.requestHeaders)
256                +   Objects.hashCode(this.responseTime)
257                +   this.responseStatus
258                +   Objects.hashCode(this.responseStatusText)
259                +   Objects.hashCode(this.responseType)
260                +   Arrays.deepHashCode(this.responseHeaders);
261        }
262    }
263    
264    /** Cache identifier. */
265    public static class Cache
266        extends BaseType
267        implements java.io.Serializable
268    {
269        /** For Object Serialization.  java.io.Serializable */
270        protected static final long serialVersionUID = 1;
271        
272        public boolean[] optionals()
273        { return new boolean[] { false, false, false, true, false, }; }
274        
275        /** An opaque unique id of the cache. */
276        public final String cacheId;
277        
278        /** Security origin of the cache. */
279        public final String securityOrigin;
280        
281        /** Storage key of the cache. */
282        public final String storageKey;
283        
284        /**
285         * Storage bucket of the cache.
286         * <BR /><B CLASS=Opt>OPTIONAL</B>
287         */
288        public final Storage.StorageBucket storageBucket;
289        
290        /** The name of the cache. */
291        public final String cacheName;
292        
293        /**
294         * Constructor
295         *
296         * @param cacheId An opaque unique id of the cache.
297         * 
298         * @param securityOrigin Security origin of the cache.
299         * 
300         * @param storageKey Storage key of the cache.
301         * 
302         * @param storageBucket Storage bucket of the cache.
303         * <BR /><B CLASS=Opt>OPTIONAL</B>
304         * 
305         * @param cacheName The name of the cache.
306         */
307        public Cache(
308                String cacheId, String securityOrigin, String storageKey, 
309                Storage.StorageBucket storageBucket, String cacheName
310            )
311        {
312            // Exception-Check(s) to ensure that if any parameters which are not declared as
313            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
314            
315            if (cacheId == null)        THROWS.throwNPE("cacheId");
316            if (securityOrigin == null) THROWS.throwNPE("securityOrigin");
317            if (storageKey == null)     THROWS.throwNPE("storageKey");
318            if (cacheName == null)      THROWS.throwNPE("cacheName");
319            
320            this.cacheId         = cacheId;
321            this.securityOrigin  = securityOrigin;
322            this.storageKey      = storageKey;
323            this.storageBucket   = storageBucket;
324            this.cacheName       = cacheName;
325        }
326        
327        /**
328         * JSON Object Constructor
329         * @param jo A Json-Object having data about an instance of {@code 'Cache'}.
330         */
331        public Cache (JsonObject jo)
332        {
333            this.cacheId         = ReadJSON.getString(jo, "cacheId", false, true);
334            this.securityOrigin  = ReadJSON.getString(jo, "securityOrigin", false, true);
335            this.storageKey      = ReadJSON.getString(jo, "storageKey", false, true);
336            this.storageBucket   = ReadJSON.getObject(jo, "storageBucket", Storage.StorageBucket.class, true, false);
337            this.cacheName       = ReadJSON.getString(jo, "cacheName", false, true);
338        }
339        
340        
341        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
342        public boolean equals(Object other)
343        {
344            if (this == other)                       return true;
345            if (other == null)                       return false;
346            if (other.getClass() != this.getClass()) return false;
347        
348            Cache o = (Cache) other;
349        
350            return
351                    Objects.equals(this.cacheId, o.cacheId)
352                &&  Objects.equals(this.securityOrigin, o.securityOrigin)
353                &&  Objects.equals(this.storageKey, o.storageKey)
354                &&  Objects.equals(this.storageBucket, o.storageBucket)
355                &&  Objects.equals(this.cacheName, o.cacheName);
356        }
357        
358        /** Generates a Hash-Code for {@code 'this'} instance */
359        public int hashCode()
360        {
361            return
362                    Objects.hashCode(this.cacheId)
363                +   Objects.hashCode(this.securityOrigin)
364                +   Objects.hashCode(this.storageKey)
365                +   this.storageBucket.hashCode()
366                +   Objects.hashCode(this.cacheName);
367        }
368    }
369    
370    /** <CODE>[No Description Provided by Google]</CODE> */
371    public static class Header
372        extends BaseType
373        implements java.io.Serializable
374    {
375        /** For Object Serialization.  java.io.Serializable */
376        protected static final long serialVersionUID = 1;
377        
378        public boolean[] optionals()
379        { return new boolean[] { false, false, }; }
380        
381        /** <CODE>[No Description Provided by Google]</CODE> */
382        public final String name;
383        
384        /** <CODE>[No Description Provided by Google]</CODE> */
385        public final String value;
386        
387        /**
388         * Constructor
389         *
390         * @param name -
391         * 
392         * @param value -
393         */
394        public Header(String name, String value)
395        {
396            // Exception-Check(s) to ensure that if any parameters which are not declared as
397            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
398            
399            if (name == null)  THROWS.throwNPE("name");
400            if (value == null) THROWS.throwNPE("value");
401            
402            this.name   = name;
403            this.value  = value;
404        }
405        
406        /**
407         * JSON Object Constructor
408         * @param jo A Json-Object having data about an instance of {@code 'Header'}.
409         */
410        public Header (JsonObject jo)
411        {
412            this.name   = ReadJSON.getString(jo, "name", false, true);
413            this.value  = ReadJSON.getString(jo, "value", false, true);
414        }
415        
416        
417        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
418        public boolean equals(Object other)
419        {
420            if (this == other)                       return true;
421            if (other == null)                       return false;
422            if (other.getClass() != this.getClass()) return false;
423        
424            Header o = (Header) other;
425        
426            return
427                    Objects.equals(this.name, o.name)
428                &&  Objects.equals(this.value, o.value);
429        }
430        
431        /** Generates a Hash-Code for {@code 'this'} instance */
432        public int hashCode()
433        {
434            return
435                    Objects.hashCode(this.name)
436                +   Objects.hashCode(this.value);
437        }
438    }
439    
440    /** Cached response */
441    public static class CachedResponse
442        extends BaseType
443        implements java.io.Serializable
444    {
445        /** For Object Serialization.  java.io.Serializable */
446        protected static final long serialVersionUID = 1;
447        
448        public boolean[] optionals()
449        { return new boolean[] { false, }; }
450        
451        /** Entry content, base64-encoded. (Encoded as a base64 string when passed over JSON) */
452        public final String body;
453        
454        /**
455         * Constructor
456         *
457         * @param body Entry content, base64-encoded. (Encoded as a base64 string when passed over JSON)
458         */
459        public CachedResponse(String body)
460        {
461            // Exception-Check(s) to ensure that if any parameters which are not declared as
462            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
463            
464            if (body == null) THROWS.throwNPE("body");
465            
466            this.body  = body;
467        }
468        
469        /**
470         * JSON Object Constructor
471         * @param jo A Json-Object having data about an instance of {@code 'CachedResponse'}.
472         */
473        public CachedResponse (JsonObject jo)
474        {
475            this.body  = ReadJSON.getString(jo, "body", false, true);
476        }
477        
478        
479        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
480        public boolean equals(Object other)
481        {
482            if (this == other)                       return true;
483            if (other == null)                       return false;
484            if (other.getClass() != this.getClass()) return false;
485        
486            CachedResponse o = (CachedResponse) other;
487        
488            return
489                    Objects.equals(this.body, o.body);
490        }
491        
492        /** Generates a Hash-Code for {@code 'this'} instance */
493        public int hashCode()
494        {
495            return
496                    Objects.hashCode(this.body);
497        }
498    }
499    
500    
501    // Counter for keeping the WebSocket Request ID's distinct.
502    private static int counter = 1;
503    
504    /**
505     * Deletes a cache.
506     * 
507     * @param cacheId Id of cache for deletion.
508     * 
509     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
510     * {@link Ret0}&gt;</CODE>
511     *
512     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
513     * browser receives the invocation-request.
514     *
515     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
516     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
517     * {@code >} to ensure the Browser Function has run to completion.
518     */
519    public static Script<String, JsonObject, Ret0> deleteCache(String cacheId)
520    {
521        // Exception-Check(s) to ensure that if any parameters which are not declared as
522        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
523        
524        if (cacheId == null) THROWS.throwNPE("cacheId");
525        
526        final int       webSocketID = 15000000 + counter++;
527        final boolean[] optionals   = { false, };
528        
529        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
530        String requestJSON = WriteJSON.get(
531            parameterTypes.get("deleteCache"),
532            parameterNames.get("deleteCache"),
533            optionals, webSocketID,
534            "CacheStorage.deleteCache",
535            cacheId
536        );
537        
538        // This Remote Command does not have a Return-Value.
539        return new Script<>
540            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
541    }
542    
543    /**
544     * Deletes a cache entry.
545     * 
546     * @param cacheId Id of cache where the entry will be deleted.
547     * 
548     * @param request URL spec of the request.
549     * 
550     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
551     * {@link Ret0}&gt;</CODE>
552     *
553     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
554     * browser receives the invocation-request.
555     *
556     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
557     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
558     * {@code >} to ensure the Browser Function has run to completion.
559     */
560    public static Script<String, JsonObject, Ret0> deleteEntry(String cacheId, String request)
561    {
562        // Exception-Check(s) to ensure that if any parameters which are not declared as
563        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
564        
565        if (cacheId == null) THROWS.throwNPE("cacheId");
566        if (request == null) THROWS.throwNPE("request");
567        
568        final int       webSocketID = 15001000 + counter++;
569        final boolean[] optionals   = { false, false, };
570        
571        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
572        String requestJSON = WriteJSON.get(
573            parameterTypes.get("deleteEntry"),
574            parameterNames.get("deleteEntry"),
575            optionals, webSocketID,
576            "CacheStorage.deleteEntry",
577            cacheId, request
578        );
579        
580        // This Remote Command does not have a Return-Value.
581        return new Script<>
582            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
583    }
584    
585    /**
586     * Requests cache names.
587     * 
588     * @param securityOrigin 
589     * At least and at most one of securityOrigin, storageKey, storageBucket must be specified.
590     * Security origin.
591     * <BR /><B CLASS=Opt>OPTIONAL</B>
592     * 
593     * @param storageKey Storage key.
594     * <BR /><B CLASS=Opt>OPTIONAL</B>
595     * 
596     * @param storageBucket Storage bucket. If not specified, it uses the default bucket.
597     * <BR /><B CLASS=Opt>OPTIONAL</B>
598     * 
599     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
600     * {@link CacheStorage.Cache}[]&gt;</CODE>
601     * 
602     * <BR /><BR />This <B>script</B> may be <B STYLE='color: red'>executed</B>, using
603     * {@link Script#exec()}, and afterwards, a {@link Promise}<CODE>&lt;JsonObject,
604     * {@link CacheStorage.Cache}[]&gt;</CODE> will be returned.
605     *
606     * <BR /><BR />Finally, the <B>{@code Promise}</B> may be <B STYLE='color: red'>awaited</B>,
607     * using {@link Promise#await()}, <I>and the returned result of this Browser Function may
608      * may be retrieved.</I>
609     *
610     * <BR /><BR />This Browser Function <B STYLE='color: red'>returns</B>
611     * <BR /><BR /><UL CLASS=JDUL>
612     * <LI><CODE>{@link CacheStorage.Cache}[] (<B>caches</B></CODE>)
613     *     <BR />Caches for the security origin.
614     * </LI>
615     * </UL> */
616    public static Script<String, JsonObject, CacheStorage.Cache[]> requestCacheNames
617        (String securityOrigin, String storageKey, Storage.StorageBucket storageBucket)
618    {
619        final int       webSocketID = 15002000 + counter++;
620        final boolean[] optionals   = { true, true, true, };
621        
622        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
623        String requestJSON = WriteJSON.get(
624            parameterTypes.get("requestCacheNames"),
625            parameterNames.get("requestCacheNames"),
626            optionals, webSocketID,
627            "CacheStorage.requestCacheNames",
628            securityOrigin, storageKey, storageBucket
629        );
630        
631        // 'JSON Binding' ... Converts Browser Response-JSON to 'CacheStorage.Cache[]'
632        Function<JsonObject, CacheStorage.Cache[]> responseProcessor = (JsonObject jo) ->
633            (jo.getJsonArray("caches") == null)
634                ? null
635                : RJArrIntoStream.objArr(jo.getJsonArray("caches"), null, 0, CacheStorage.Cache.class).toArray(CacheStorage.Cache[]::new);
636        
637        return new Script<>(webSocketID, requestJSON, responseProcessor);
638    }
639    
640    /**
641     * Fetches cache entry.
642     * 
643     * @param cacheId Id of cache that contains the entry.
644     * 
645     * @param requestURL URL spec of the request.
646     * 
647     * @param requestHeaders headers of the request.
648     * 
649     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
650     * {@link CacheStorage.CachedResponse}&gt;</CODE>
651     * 
652     * <BR /><BR />This <B>script</B> may be <B STYLE='color: red'>executed</B>, using
653     * {@link Script#exec()}, and afterwards, a {@link Promise}<CODE>&lt;JsonObject,
654     * {@link CacheStorage.CachedResponse}&gt;</CODE> will be returned.
655     *
656     * <BR /><BR />Finally, the <B>{@code Promise}</B> may be <B STYLE='color: red'>awaited</B>,
657     * using {@link Promise#await()}, <I>and the returned result of this Browser Function may
658      * may be retrieved.</I>
659     *
660     * <BR /><BR />This Browser Function <B STYLE='color: red'>returns</B>
661     * <BR /><BR /><UL CLASS=JDUL>
662     * <LI><CODE>{@link CacheStorage.CachedResponse} (<B>response</B></CODE>)
663     *     <BR />Response read from the cache.
664     * </LI>
665     * </UL> */
666    public static Script<String, JsonObject, CacheStorage.CachedResponse> requestCachedResponse
667        (String cacheId, String requestURL, CacheStorage.Header[] requestHeaders)
668    {
669        // Exception-Check(s) to ensure that if any parameters which are not declared as
670        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
671        
672        if (cacheId == null)        THROWS.throwNPE("cacheId");
673        if (requestURL == null)     THROWS.throwNPE("requestURL");
674        if (requestHeaders == null) THROWS.throwNPE("requestHeaders");
675        
676        final int       webSocketID = 15003000 + counter++;
677        final boolean[] optionals   = { false, false, false, };
678        
679        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
680        String requestJSON = WriteJSON.get(
681            parameterTypes.get("requestCachedResponse"),
682            parameterNames.get("requestCachedResponse"),
683            optionals, webSocketID,
684            "CacheStorage.requestCachedResponse",
685            cacheId, requestURL, requestHeaders
686        );
687        
688        // 'JSON Binding' ... Converts Browser Response-JSON to 'CacheStorage.CachedResponse'
689        Function<JsonObject, CacheStorage.CachedResponse> responseProcessor = (JsonObject jo) ->
690            ReadJSON.getObject(jo, "response", CacheStorage.CachedResponse.class, false, true);
691        
692        return new Script<>(webSocketID, requestJSON, responseProcessor);
693    }
694    
695    /**
696     * Requests data from cache.
697     * 
698     * @param cacheId ID of cache to get entries from.
699     * 
700     * @param skipCount Number of records to skip.
701     * <BR /><B CLASS=Opt>OPTIONAL</B>
702     * 
703     * @param pageSize Number of records to fetch.
704     * <BR /><B CLASS=Opt>OPTIONAL</B>
705     * 
706     * @param pathFilter If present, only return the entries containing this substring in the path
707     * <BR /><B CLASS=Opt>OPTIONAL</B>
708     * 
709     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
710     * {@link Ret2}&gt;</CODE>
711     *
712     * <BR /><BR />This {@link Script} may be <B STYLE='color:red'>executed</B> (using 
713     * {@link Script#exec()}), and a {@link Promise} returned.
714     *
715     * <BR /><BR />When the {@code Promise} is <B STYLE='color: red'>awaited</B>
716     * (using {@link Promise#await()}), the {@code Ret2} will subsequently
717     * be returned from that call.
718     * 
719     * <BR /><BR />The <B STYLE='color: red'>returned</B> values are encapsulated
720     * in an instance of <B>{@link Ret2}</B>
721     *
722     * <BR /><BR /><UL CLASS=JDUL>
723     * <LI><CODE><B>Ret2.a:</B> {@link CacheStorage.DataEntry}[] (<B>cacheDataEntries</B>)</CODE>
724     *     <BR />Array of object store data entries.
725     *     <BR /><BR /></LI>
726     * <LI><CODE><B>Ret2.b:</B> Number (<B>returnCount</B>)</CODE>
727     *     <BR />Count of returned entries from this storage. If pathFilter is empty, it
728     *     is the count of all entries from this storage.
729     *     </LI>
730     * </UL>
731     */
732    public static Script<String, JsonObject, Ret2<CacheStorage.DataEntry[], Number>> requestEntries
733        (String cacheId, Integer skipCount, Integer pageSize, String pathFilter)
734    {
735        // Exception-Check(s) to ensure that if any parameters which are not declared as
736        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
737        
738        if (cacheId == null) THROWS.throwNPE("cacheId");
739        
740        final int       webSocketID = 15004000 + counter++;
741        final boolean[] optionals   = { false, true, true, true, };
742        
743        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
744        String requestJSON = WriteJSON.get(
745            parameterTypes.get("requestEntries"),
746            parameterNames.get("requestEntries"),
747            optionals, webSocketID,
748            "CacheStorage.requestEntries",
749            cacheId, skipCount, pageSize, pathFilter
750        );
751        
752        // 'JSON Binding' ... Converts Browser Response-JSON into Java-Type 'Ret2'
753        Function<JsonObject, Ret2<CacheStorage.DataEntry[], Number>>
754            responseProcessor = (JsonObject jo) -> new Ret2<>(
755                (jo.getJsonArray("cacheDataEntries") == null)
756                    ? null
757                    : RJArrIntoStream.objArr(jo.getJsonArray("cacheDataEntries"), null, 0, CacheStorage.DataEntry.class).toArray(CacheStorage.DataEntry[]::new),
758                ReadNumberJSON.get(jo, "returnCount", false, true)
759            );
760        
761        return new Script<>(webSocketID, requestJSON, responseProcessor);
762    }
763    
764}