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>A domain for interacting with Cast, Presentation API, and Remote Playback API
024 * functionalities.</B></SPAN>
025 * 
026 * <EMBED CLASS='external-html' DATA-FILE-ID=CODE_GEN_NOTE>
027 */
028@StaticFunctional(Excused={"counter"}, Excuses={Excuse.CONFIGURATION})
029@JDHeaderBackgroundImg(EmbedTagFileID="WOOD_PLANK_NOTE")
030public class Cast
031{
032    // ********************************************************************************************
033    // ********************************************************************************************
034    // Class Header Stuff
035    // ********************************************************************************************
036    // ********************************************************************************************
037
038
039    // No Pubic Constructors
040    private Cast () { }
041
042    // These two Vector's are used by all the "Methods" exported by this class.  java.lang.reflect
043    // is used to generate the JSON String's.  It saves thousands of lines of Auto-Generated Code.
044    private static final Map<String, Vector<String>>    parameterNames = new HashMap<>();
045    private static final Map<String, Vector<Class<?>>>  parameterTypes = new HashMap<>();
046
047    // Some Methods do not take any parameters - for instance all the "enable()" and "disable()"
048    // I simply could not get ride of RAW-TYPES and UNCHECKED warnings... so there are now,
049    // offically, two empty-vectors.  One for String's, and the other for Classes.
050
051    private static final Vector<String>     EMPTY_VEC_STR = new Vector<>();
052    private static final Vector<Class<?>>   EMPTY_VEC_CLASS = new Vector<>();
053
054    static
055    {
056        for (Method m : Cast.class.getMethods())
057        {
058            // This doesn't work!  The parameter names are all "arg0" ... "argN"
059            // It works for java.lang.reflect.Field, BUT NOT java.lang.reflect.Parameter!
060            //
061            // Vector<String> parameterNamesList = new Vector<>(); -- NOPE!
062
063            Vector<Class<?>> parameterTypesList = new Vector<>();
064        
065            for (Parameter p : m.getParameters()) parameterTypesList.add(p.getType());
066
067            parameterTypes.put(
068                m.getName(),
069                (parameterTypesList.size() > 0) ? parameterTypesList : EMPTY_VEC_CLASS
070            );
071        }
072    }
073
074    static
075    {
076        Vector<String> v = null;
077
078        v = new Vector<String>(1);
079        parameterNames.put("enable", v);
080        Collections.addAll(v, new String[]
081        { "presentationUrl", });
082
083        parameterNames.put("disable", EMPTY_VEC_STR);
084
085        v = new Vector<String>(1);
086        parameterNames.put("setSinkToUse", v);
087        Collections.addAll(v, new String[]
088        { "sinkName", });
089
090        v = new Vector<String>(1);
091        parameterNames.put("startTabMirroring", v);
092        Collections.addAll(v, new String[]
093        { "sinkName", });
094
095        v = new Vector<String>(1);
096        parameterNames.put("stopCasting", v);
097        Collections.addAll(v, new String[]
098        { "sinkName", });
099    }
100
101
102    // ********************************************************************************************
103    // ********************************************************************************************
104    // Types - Static Inner Classes
105    // ********************************************************************************************
106    // ********************************************************************************************
107
108    /** <CODE>[No Description Provided by Google]</CODE> */
109    public static class Sink
110        extends BaseType
111        implements java.io.Serializable
112    {
113        /** For Object Serialization.  java.io.Serializable */
114        protected static final long serialVersionUID = 1;
115        
116        public boolean[] optionals()
117        { return new boolean[] { false, false, true, }; }
118        
119        /** <CODE>[No Description Provided by Google]</CODE> */
120        public final String name;
121        
122        /** <CODE>[No Description Provided by Google]</CODE> */
123        public final String id;
124        
125        /**
126         * Text describing the current session. Present only if there is an active
127         * session on the sink.
128         * <BR />
129         * <BR /><B>OPTIONAL</B>
130         */
131        public final String session;
132        
133        /**
134         * Constructor
135         *
136         * @param name -
137         * 
138         * @param id -
139         * 
140         * @param session 
141         * Text describing the current session. Present only if there is an active
142         * session on the sink.
143         * <BR /><B>OPTIONAL</B>
144         */
145        public Sink(String name, String id, String session)
146        {
147            // Exception-Check(s) to ensure that if any parameters which are not declared as
148            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
149            
150            if (name == null) BRDPC.throwNPE("name");
151            if (id == null)   BRDPC.throwNPE("id");
152            
153            this.name     = name;
154            this.id       = id;
155            this.session  = session;
156        }
157        
158        /**
159         * JSON Object Constructor
160         * @param jo A Json-Object having data about an instance of {@code 'Sink'}.
161         */
162        public Sink (JsonObject jo)
163        {
164            this.name     = ReadJSON.getString(jo, "name", false, true);
165            this.id       = ReadJSON.getString(jo, "id", false, true);
166            this.session  = ReadJSON.getString(jo, "session", true, false);
167        }
168        
169        
170        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
171        public boolean equals(Object other)
172        {
173            if (other == null)                       return false;
174            if (other.getClass() != this.getClass()) return false;
175        
176            Sink o = (Sink) other;
177        
178            return
179                    Objects.equals(this.name, o.name)
180                &&  Objects.equals(this.id, o.id)
181                &&  Objects.equals(this.session, o.session);
182        }
183        
184        /** Generates a Hash-Code for {@code 'this'} instance */
185        public int hashCode()
186        {
187            return
188                    Objects.hashCode(this.name)
189                +   Objects.hashCode(this.id)
190                +   Objects.hashCode(this.session);
191        }
192    }
193    
194    /**
195     * This is fired whenever the list of available sinks changes. A sink is a
196     * device or a software surface that you can cast to.
197     */
198    public static class sinksUpdated
199        extends BrowserEvent
200        implements java.io.Serializable
201    {
202        /** For Object Serialization.  java.io.Serializable */
203        protected static final long serialVersionUID = 1;
204        
205        public boolean[] optionals()
206        { return new boolean[] { false, }; }
207        
208        /** <CODE>[No Description Provided by Google]</CODE> */
209        public final Cast.Sink[] sinks;
210        
211        /**
212         * Constructor
213         *
214         * @param sinks -
215         */
216        public sinksUpdated(Cast.Sink[] sinks)
217        {
218            super("Cast", "sinksUpdated", 1);
219            
220            // Exception-Check(s) to ensure that if any parameters which are not declared as
221            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
222            
223            if (sinks == null) BRDPC.throwNPE("sinks");
224            
225            this.sinks  = sinks;
226        }
227        
228        /**
229         * JSON Object Constructor
230         * @param jo A Json-Object having data about an instance of {@code 'sinksUpdated'}.
231         */
232        public sinksUpdated (JsonObject jo)
233        {
234            super("Cast", "sinksUpdated", 1);
235        
236            this.sinks = (jo.getJsonArray("sinks") == null)
237                ? null
238                : ReadArrJSON.DimN.objArr(jo.getJsonArray("sinks"), null, 0, Cast.Sink[].class);
239        
240        }
241        
242        
243        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
244        public boolean equals(Object other)
245        {
246            if (other == null)                       return false;
247            if (other.getClass() != this.getClass()) return false;
248        
249            sinksUpdated o = (sinksUpdated) other;
250        
251            return
252                    Arrays.deepEquals(this.sinks, o.sinks);
253        }
254        
255        /** Generates a Hash-Code for {@code 'this'} instance */
256        public int hashCode()
257        {
258            return
259                    Arrays.deepHashCode(this.sinks);
260        }
261    }
262    
263    /**
264     * This is fired whenever the outstanding issue/error message changes.
265     * |issueMessage| is empty if there is no issue.
266     */
267    public static class issueUpdated
268        extends BrowserEvent
269        implements java.io.Serializable
270    {
271        /** For Object Serialization.  java.io.Serializable */
272        protected static final long serialVersionUID = 1;
273        
274        public boolean[] optionals()
275        { return new boolean[] { false, }; }
276        
277        /** <CODE>[No Description Provided by Google]</CODE> */
278        public final String issueMessage;
279        
280        /**
281         * Constructor
282         *
283         * @param issueMessage -
284         */
285        public issueUpdated(String issueMessage)
286        {
287            super("Cast", "issueUpdated", 1);
288            
289            // Exception-Check(s) to ensure that if any parameters which are not declared as
290            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
291            
292            if (issueMessage == null) BRDPC.throwNPE("issueMessage");
293            
294            this.issueMessage  = issueMessage;
295        }
296        
297        /**
298         * JSON Object Constructor
299         * @param jo A Json-Object having data about an instance of {@code 'issueUpdated'}.
300         */
301        public issueUpdated (JsonObject jo)
302        {
303            super("Cast", "issueUpdated", 1);
304        
305            this.issueMessage  = ReadJSON.getString(jo, "issueMessage", false, true);
306        }
307        
308        
309        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
310        public boolean equals(Object other)
311        {
312            if (other == null)                       return false;
313            if (other.getClass() != this.getClass()) return false;
314        
315            issueUpdated o = (issueUpdated) other;
316        
317            return
318                    Objects.equals(this.issueMessage, o.issueMessage);
319        }
320        
321        /** Generates a Hash-Code for {@code 'this'} instance */
322        public int hashCode()
323        {
324            return
325                    Objects.hashCode(this.issueMessage);
326        }
327    }
328    
329    
330    // Counter for keeping the WebSocket Request ID's distinct.
331    private static int counter = 1;
332    
333    /**
334     * Starts observing for sinks that can be used for tab mirroring, and if set,
335     * sinks compatible with |presentationUrl| as well. When sinks are found, a
336     * |sinksUpdated| event is fired.
337     * Also starts observing for issue messages. When an issue is added or removed,
338     * an |issueUpdated| event is fired.
339     * 
340     * @param presentationUrl -
341     * <BR /><B>OPTIONAL</B>
342     * 
343     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
344     * {@link Ret0}&gt;</CODE>
345     *
346     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
347     * browser receives the invocation-request.
348     *
349     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
350     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
351     * {@code >} to ensure the Browser Function has run to completion.
352     */
353    public static Script<String, JsonObject, Ret0> enable(String presentationUrl)
354    {
355        final int       webSocketID = 14000000 + counter++;
356        final boolean[] optionals   = { true, };
357        
358        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
359        String requestJSON = WriteJSON.get(
360            parameterTypes.get("enable"),
361            parameterNames.get("enable"),
362            optionals, webSocketID,
363            "Cast.enable",
364            presentationUrl
365        );
366        
367        // This Remote Command does not have a Return-Value.
368        return new Script<>
369            (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues);
370    }
371    
372    /**
373     * Stops observing for sinks and issues.
374     * 
375     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
376     * {@link Ret0}&gt;</CODE>
377     *
378     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
379     * browser receives the invocation-request.
380     *
381     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
382     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
383     * {@code >} to ensure the Browser Function has run to completion.
384     */
385    public static Script<String, JsonObject, Ret0> disable()
386    {
387        final int          webSocketID = 14001000 + counter++;
388        final boolean[]    optionals   = new boolean[0];
389        
390        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
391        String requestJSON = WriteJSON.get(
392            parameterTypes.get("disable"),
393            parameterNames.get("disable"),
394            optionals, webSocketID,
395            "Cast.disable"
396        );
397        
398        // This Remote Command does not have a Return-Value.
399        return new Script<>
400            (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues);
401    }
402    
403    /**
404     * Sets a sink to be used when the web page requests the browser to choose a
405     * sink via Presentation API, Remote Playback API, or Cast SDK.
406     * 
407     * @param sinkName -
408     * 
409     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
410     * {@link Ret0}&gt;</CODE>
411     *
412     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
413     * browser receives the invocation-request.
414     *
415     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
416     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
417     * {@code >} to ensure the Browser Function has run to completion.
418     */
419    public static Script<String, JsonObject, Ret0> setSinkToUse(String sinkName)
420    {
421        // Exception-Check(s) to ensure that if any parameters which are not declared as
422        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
423        
424        if (sinkName == null) BRDPC.throwNPE("sinkName");
425        
426        final int       webSocketID = 14002000 + counter++;
427        final boolean[] optionals   = { false, };
428        
429        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
430        String requestJSON = WriteJSON.get(
431            parameterTypes.get("setSinkToUse"),
432            parameterNames.get("setSinkToUse"),
433            optionals, webSocketID,
434            "Cast.setSinkToUse",
435            sinkName
436        );
437        
438        // This Remote Command does not have a Return-Value.
439        return new Script<>
440            (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues);
441    }
442    
443    /**
444     * Starts mirroring the tab to the sink.
445     * 
446     * @param sinkName -
447     * 
448     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
449     * {@link Ret0}&gt;</CODE>
450     *
451     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
452     * browser receives the invocation-request.
453     *
454     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
455     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
456     * {@code >} to ensure the Browser Function has run to completion.
457     */
458    public static Script<String, JsonObject, Ret0> startTabMirroring(String sinkName)
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 (sinkName == null) BRDPC.throwNPE("sinkName");
464        
465        final int       webSocketID = 14003000 + counter++;
466        final boolean[] optionals   = { false, };
467        
468        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
469        String requestJSON = WriteJSON.get(
470            parameterTypes.get("startTabMirroring"),
471            parameterNames.get("startTabMirroring"),
472            optionals, webSocketID,
473            "Cast.startTabMirroring",
474            sinkName
475        );
476        
477        // This Remote Command does not have a Return-Value.
478        return new Script<>
479            (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues);
480    }
481    
482    /**
483     * Stops the active Cast session on the sink.
484     * 
485     * @param sinkName -
486     * 
487     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
488     * {@link Ret0}&gt;</CODE>
489     *
490     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
491     * browser receives the invocation-request.
492     *
493     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
494     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
495     * {@code >} to ensure the Browser Function has run to completion.
496     */
497    public static Script<String, JsonObject, Ret0> stopCasting(String sinkName)
498    {
499        // Exception-Check(s) to ensure that if any parameters which are not declared as
500        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
501        
502        if (sinkName == null) BRDPC.throwNPE("sinkName");
503        
504        final int       webSocketID = 14004000 + counter++;
505        final boolean[] optionals   = { false, };
506        
507        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
508        String requestJSON = WriteJSON.get(
509            parameterTypes.get("stopCasting"),
510            parameterNames.get("stopCasting"),
511            optionals, webSocketID,
512            "Cast.stopCasting",
513            sinkName
514        );
515        
516        // This Remote Command does not have a Return-Value.
517        return new Script<>
518            (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues);
519    }
520    
521}