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>Defines events for background web platform features.</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 BackgroundService
030{
031    // ********************************************************************************************
032    // ********************************************************************************************
033    // Class Header Stuff
034    // ********************************************************************************************
035    // ********************************************************************************************
036
037
038    // No Pubic Constructors
039    private BackgroundService () { }
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 : BackgroundService.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>(1);
078        parameterNames.put("startObserving", v);
079        Collections.addAll(v, new String[]
080        { "service", });
081
082        v = new Vector<String>(1);
083        parameterNames.put("stopObserving", v);
084        Collections.addAll(v, new String[]
085        { "service", });
086
087        v = new Vector<String>(2);
088        parameterNames.put("setRecording", v);
089        Collections.addAll(v, new String[]
090        { "shouldRecord", "service", });
091
092        v = new Vector<String>(1);
093        parameterNames.put("clearEvents", v);
094        Collections.addAll(v, new String[]
095        { "service", });
096    }
097
098
099    // ********************************************************************************************
100    // ********************************************************************************************
101    // Types - Static Inner Classes
102    // ********************************************************************************************
103    // ********************************************************************************************
104
105    /**
106     * The Background Service that will be associated with the commands/events.
107     * Every Background Service operates independently, but they share the same
108     * API.
109     */
110    public static final String[] ServiceName =
111    { 
112        "backgroundFetch", "backgroundSync", "pushMessaging", "notifications", "paymentHandler", 
113        "periodicBackgroundSync", 
114    };
115    
116    /** A key-value pair for additional event information to pass along. */
117    public static class EventMetadata
118        extends BaseType
119        implements java.io.Serializable
120    {
121        /** For Object Serialization.  java.io.Serializable */
122        protected static final long serialVersionUID = 1;
123        
124        public boolean[] optionals()
125        { return new boolean[] { false, false, }; }
126        
127        /** <CODE>[No Description Provided by Google]</CODE> */
128        public final String key;
129        
130        /** <CODE>[No Description Provided by Google]</CODE> */
131        public final String value;
132        
133        /**
134         * Constructor
135         *
136         * @param key -
137         * 
138         * @param value -
139         */
140        public EventMetadata(String key, String value)
141        {
142            // Exception-Check(s) to ensure that if any parameters which are not declared as
143            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
144            
145            if (key == null)   BRDPC.throwNPE("key");
146            if (value == null) BRDPC.throwNPE("value");
147            
148            this.key    = key;
149            this.value  = value;
150        }
151        
152        /**
153         * JSON Object Constructor
154         * @param jo A Json-Object having data about an instance of {@code 'EventMetadata'}.
155         */
156        public EventMetadata (JsonObject jo)
157        {
158            this.key    = ReadJSON.getString(jo, "key", false, true);
159            this.value  = ReadJSON.getString(jo, "value", false, true);
160        }
161        
162        
163        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
164        public boolean equals(Object other)
165        {
166            if (other == null)                       return false;
167            if (other.getClass() != this.getClass()) return false;
168        
169            EventMetadata o = (EventMetadata) other;
170        
171            return
172                    Objects.equals(this.key, o.key)
173                &&  Objects.equals(this.value, o.value);
174        }
175        
176        /** Generates a Hash-Code for {@code 'this'} instance */
177        public int hashCode()
178        {
179            return
180                    Objects.hashCode(this.key)
181                +   Objects.hashCode(this.value);
182        }
183    }
184    
185    /** <CODE>[No Description Provided by Google]</CODE> */
186    public static class BackgroundServiceEvent
187        extends BaseType
188        implements java.io.Serializable
189    {
190        /** For Object Serialization.  java.io.Serializable */
191        protected static final long serialVersionUID = 1;
192        
193        public boolean[] optionals()
194        { return new boolean[] { false, false, false, false, false, false, false, }; }
195        
196        /** Timestamp of the event (in seconds). */
197        public final Number timestamp;
198        
199        /** The origin this event belongs to. */
200        public final String origin;
201        
202        /** The Service Worker ID that initiated the event. */
203        public final String serviceWorkerRegistrationId;
204        
205        /** The Background Service this event belongs to. */
206        public final String service;
207        
208        /** A description of the event. */
209        public final String eventName;
210        
211        /** An identifier that groups related events together. */
212        public final String instanceId;
213        
214        /** A list of event-specific information. */
215        public final BackgroundService.EventMetadata[] eventMetadata;
216        
217        /**
218         * Constructor
219         *
220         * @param timestamp Timestamp of the event (in seconds).
221         * 
222         * @param origin The origin this event belongs to.
223         * 
224         * @param serviceWorkerRegistrationId The Service Worker ID that initiated the event.
225         * 
226         * @param service The Background Service this event belongs to.
227         * 
228         * @param eventName A description of the event.
229         * 
230         * @param instanceId An identifier that groups related events together.
231         * 
232         * @param eventMetadata A list of event-specific information.
233         */
234        public BackgroundServiceEvent(
235                Number timestamp, String origin, String serviceWorkerRegistrationId, String service, 
236                String eventName, String instanceId, BackgroundService.EventMetadata[] eventMetadata
237            )
238        {
239            // Exception-Check(s) to ensure that if any parameters which are not declared as
240            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
241            
242            if (timestamp == null)                   BRDPC.throwNPE("timestamp");
243            if (origin == null)                      BRDPC.throwNPE("origin");
244            if (serviceWorkerRegistrationId == null) BRDPC.throwNPE("serviceWorkerRegistrationId");
245            if (service == null)                     BRDPC.throwNPE("service");
246            if (eventName == null)                   BRDPC.throwNPE("eventName");
247            if (instanceId == null)                  BRDPC.throwNPE("instanceId");
248            if (eventMetadata == null)               BRDPC.throwNPE("eventMetadata");
249            
250            // Exception-Check(s) to ensure that if any parameters which must adhere to a
251            // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
252            
253            BRDPC.checkIAE("service", service, "BackgroundService.ServiceName", BackgroundService.ServiceName);
254            
255            this.timestamp                    = timestamp;
256            this.origin                       = origin;
257            this.serviceWorkerRegistrationId  = serviceWorkerRegistrationId;
258            this.service                      = service;
259            this.eventName                    = eventName;
260            this.instanceId                   = instanceId;
261            this.eventMetadata                = eventMetadata;
262        }
263        
264        /**
265         * JSON Object Constructor
266         * @param jo A Json-Object having data about an instance of {@code 'BackgroundServiceEvent'}.
267         */
268        public BackgroundServiceEvent (JsonObject jo)
269        {
270            this.timestamp                    = ReadNumberJSON.get(jo, "timestamp", false, true);
271            this.origin                       = ReadJSON.getString(jo, "origin", false, true);
272            this.serviceWorkerRegistrationId  = ReadJSON.getString(jo, "serviceWorkerRegistrationId", false, true);
273            this.service                      = ReadJSON.getString(jo, "service", false, true);
274            this.eventName                    = ReadJSON.getString(jo, "eventName", false, true);
275            this.instanceId                   = ReadJSON.getString(jo, "instanceId", false, true);
276            this.eventMetadata = (jo.getJsonArray("eventMetadata") == null)
277                ? null
278                : ReadArrJSON.DimN.objArr(jo.getJsonArray("eventMetadata"), null, 0, BackgroundService.EventMetadata[].class);
279        
280        }
281        
282        
283        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
284        public boolean equals(Object other)
285        {
286            if (other == null)                       return false;
287            if (other.getClass() != this.getClass()) return false;
288        
289            BackgroundServiceEvent o = (BackgroundServiceEvent) other;
290        
291            return
292                    Objects.equals(this.timestamp, o.timestamp)
293                &&  Objects.equals(this.origin, o.origin)
294                &&  Objects.equals(this.serviceWorkerRegistrationId, o.serviceWorkerRegistrationId)
295                &&  Objects.equals(this.service, o.service)
296                &&  Objects.equals(this.eventName, o.eventName)
297                &&  Objects.equals(this.instanceId, o.instanceId)
298                &&  Arrays.deepEquals(this.eventMetadata, o.eventMetadata);
299        }
300        
301        /** Generates a Hash-Code for {@code 'this'} instance */
302        public int hashCode()
303        {
304            return
305                    Objects.hashCode(this.timestamp)
306                +   Objects.hashCode(this.origin)
307                +   Objects.hashCode(this.serviceWorkerRegistrationId)
308                +   Objects.hashCode(this.service)
309                +   Objects.hashCode(this.eventName)
310                +   Objects.hashCode(this.instanceId)
311                +   Arrays.deepHashCode(this.eventMetadata);
312        }
313    }
314    
315    /** Called when the recording state for the service has been updated. */
316    public static class recordingStateChanged
317        extends BrowserEvent
318        implements java.io.Serializable
319    {
320        /** For Object Serialization.  java.io.Serializable */
321        protected static final long serialVersionUID = 1;
322        
323        public boolean[] optionals()
324        { return new boolean[] { false, false, }; }
325        
326        /** <CODE>[No Description Provided by Google]</CODE> */
327        public final boolean isRecording;
328        
329        /** <CODE>[No Description Provided by Google]</CODE> */
330        public final String service;
331        
332        /**
333         * Constructor
334         *
335         * @param isRecording -
336         * 
337         * @param service -
338         */
339        public recordingStateChanged(boolean isRecording, String service)
340        {
341            super("BackgroundService", "recordingStateChanged", 2);
342            
343            // Exception-Check(s) to ensure that if any parameters which are not declared as
344            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
345            
346            if (service == null) BRDPC.throwNPE("service");
347            
348            // Exception-Check(s) to ensure that if any parameters which must adhere to a
349            // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
350            
351            BRDPC.checkIAE("service", service, "BackgroundService.ServiceName", BackgroundService.ServiceName);
352            
353            this.isRecording  = isRecording;
354            this.service      = service;
355        }
356        
357        /**
358         * JSON Object Constructor
359         * @param jo A Json-Object having data about an instance of {@code 'recordingStateChanged'}.
360         */
361        public recordingStateChanged (JsonObject jo)
362        {
363            super("BackgroundService", "recordingStateChanged", 2);
364        
365            this.isRecording  = ReadPrimJSON.getBoolean(jo, "isRecording");
366            this.service      = ReadJSON.getString(jo, "service", false, true);
367        }
368        
369        
370        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
371        public boolean equals(Object other)
372        {
373            if (other == null)                       return false;
374            if (other.getClass() != this.getClass()) return false;
375        
376            recordingStateChanged o = (recordingStateChanged) other;
377        
378            return
379                    (this.isRecording == o.isRecording)
380                &&  Objects.equals(this.service, o.service);
381        }
382        
383        /** Generates a Hash-Code for {@code 'this'} instance */
384        public int hashCode()
385        {
386            return
387                    (this.isRecording ? 1 : 0)
388                +   Objects.hashCode(this.service);
389        }
390    }
391    
392    /**
393     * Called with all existing backgroundServiceEvents when enabled, and all new
394     * events afterwards if enabled and recording.
395     */
396    public static class backgroundServiceEventReceived
397        extends BrowserEvent
398        implements java.io.Serializable
399    {
400        /** For Object Serialization.  java.io.Serializable */
401        protected static final long serialVersionUID = 1;
402        
403        public boolean[] optionals()
404        { return new boolean[] { false, }; }
405        
406        /** <CODE>[No Description Provided by Google]</CODE> */
407        public final BackgroundService.BackgroundServiceEvent backgroundServiceEvent;
408        
409        /**
410         * Constructor
411         *
412         * @param backgroundServiceEvent -
413         */
414        public backgroundServiceEventReceived
415            (BackgroundService.BackgroundServiceEvent backgroundServiceEvent)
416        {
417            super("BackgroundService", "backgroundServiceEventReceived", 1);
418            
419            // Exception-Check(s) to ensure that if any parameters which are not declared as
420            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
421            
422            if (backgroundServiceEvent == null) BRDPC.throwNPE("backgroundServiceEvent");
423            
424            this.backgroundServiceEvent  = backgroundServiceEvent;
425        }
426        
427        /**
428         * JSON Object Constructor
429         * @param jo A Json-Object having data about an instance of {@code 'backgroundServiceEventReceived'}.
430         */
431        public backgroundServiceEventReceived (JsonObject jo)
432        {
433            super("BackgroundService", "backgroundServiceEventReceived", 1);
434        
435            this.backgroundServiceEvent  = ReadJSON.getObject(jo, "backgroundServiceEvent", BackgroundService.BackgroundServiceEvent.class, false, true);
436        }
437        
438        
439        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
440        public boolean equals(Object other)
441        {
442            if (other == null)                       return false;
443            if (other.getClass() != this.getClass()) return false;
444        
445            backgroundServiceEventReceived o = (backgroundServiceEventReceived) other;
446        
447            return
448                    Objects.equals(this.backgroundServiceEvent, o.backgroundServiceEvent);
449        }
450        
451        /** Generates a Hash-Code for {@code 'this'} instance */
452        public int hashCode()
453        {
454            return
455                    this.backgroundServiceEvent.hashCode();
456        }
457    }
458    
459    
460    // Counter for keeping the WebSocket Request ID's distinct.
461    private static int counter = 1;
462    
463    /**
464     * Enables event updates for the service.
465     * 
466     * @param service -
467     * 
468     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
469     * {@link Ret0}&gt;</CODE>
470     *
471     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
472     * browser receives the invocation-request.
473     *
474     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
475     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
476     * {@code >} to ensure the Browser Function has run to completion.
477     */
478    public static Script<String, JsonObject, Ret0> startObserving(String service)
479    {
480        // Exception-Check(s) to ensure that if any parameters which are not declared as
481        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
482        
483        if (service == null) BRDPC.throwNPE("service");
484        
485        // Exception-Check(s) to ensure that if any parameters which must adhere to a
486        // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
487        
488        BRDPC.checkIAE("service", service, "BackgroundService.ServiceName", BackgroundService.ServiceName);
489        
490        final int       webSocketID = 10000000 + counter++;
491        final boolean[] optionals   = { false, };
492        
493        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
494        String requestJSON = WriteJSON.get(
495            parameterTypes.get("startObserving"),
496            parameterNames.get("startObserving"),
497            optionals, webSocketID,
498            "BackgroundService.startObserving",
499            service
500        );
501        
502        // This Remote Command does not have a Return-Value.
503        return new Script<>
504            (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues);
505    }
506    
507    /**
508     * Disables event updates for the service.
509     * 
510     * @param service -
511     * 
512     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
513     * {@link Ret0}&gt;</CODE>
514     *
515     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
516     * browser receives the invocation-request.
517     *
518     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
519     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
520     * {@code >} to ensure the Browser Function has run to completion.
521     */
522    public static Script<String, JsonObject, Ret0> stopObserving(String service)
523    {
524        // Exception-Check(s) to ensure that if any parameters which are not declared as
525        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
526        
527        if (service == null) BRDPC.throwNPE("service");
528        
529        // Exception-Check(s) to ensure that if any parameters which must adhere to a
530        // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
531        
532        BRDPC.checkIAE("service", service, "BackgroundService.ServiceName", BackgroundService.ServiceName);
533        
534        final int       webSocketID = 10001000 + counter++;
535        final boolean[] optionals   = { false, };
536        
537        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
538        String requestJSON = WriteJSON.get(
539            parameterTypes.get("stopObserving"),
540            parameterNames.get("stopObserving"),
541            optionals, webSocketID,
542            "BackgroundService.stopObserving",
543            service
544        );
545        
546        // This Remote Command does not have a Return-Value.
547        return new Script<>
548            (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues);
549    }
550    
551    /**
552     * Set the recording state for the service.
553     * 
554     * @param shouldRecord -
555     * 
556     * @param service -
557     * 
558     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
559     * {@link Ret0}&gt;</CODE>
560     *
561     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
562     * browser receives the invocation-request.
563     *
564     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
565     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
566     * {@code >} to ensure the Browser Function has run to completion.
567     */
568    public static Script<String, JsonObject, Ret0> setRecording
569        (boolean shouldRecord, String service)
570    {
571        // Exception-Check(s) to ensure that if any parameters which are not declared as
572        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
573        
574        if (service == null) BRDPC.throwNPE("service");
575        
576        // Exception-Check(s) to ensure that if any parameters which must adhere to a
577        // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
578        
579        BRDPC.checkIAE("service", service, "BackgroundService.ServiceName", BackgroundService.ServiceName);
580        
581        final int       webSocketID = 10002000 + counter++;
582        final boolean[] optionals   = { false, false, };
583        
584        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
585        String requestJSON = WriteJSON.get(
586            parameterTypes.get("setRecording"),
587            parameterNames.get("setRecording"),
588            optionals, webSocketID,
589            "BackgroundService.setRecording",
590            shouldRecord, service
591        );
592        
593        // This Remote Command does not have a Return-Value.
594        return new Script<>
595            (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues);
596    }
597    
598    /**
599     * Clears all stored data for the service.
600     * 
601     * @param service -
602     * 
603     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
604     * {@link Ret0}&gt;</CODE>
605     *
606     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
607     * browser receives the invocation-request.
608     *
609     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
610     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
611     * {@code >} to ensure the Browser Function has run to completion.
612     */
613    public static Script<String, JsonObject, Ret0> clearEvents(String service)
614    {
615        // Exception-Check(s) to ensure that if any parameters which are not declared as
616        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
617        
618        if (service == null) BRDPC.throwNPE("service");
619        
620        // Exception-Check(s) to ensure that if any parameters which must adhere to a
621        // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
622        
623        BRDPC.checkIAE("service", service, "BackgroundService.ServiceName", BackgroundService.ServiceName);
624        
625        final int       webSocketID = 10003000 + counter++;
626        final boolean[] optionals   = { false, };
627        
628        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
629        String requestJSON = WriteJSON.get(
630            parameterTypes.get("clearEvents"),
631            parameterNames.get("clearEvents"),
632            optionals, webSocketID,
633            "BackgroundService.clearEvents",
634            service
635        );
636        
637        // This Remote Command does not have a Return-Value.
638        return new Script<>
639            (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues);
640    }
641    
642}