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>Reporting of performance timeline events, as specified in
024 * https://w3c.github.io/performance-timeline/#dom-performanceobserver.</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 PerformanceTimeline
031{
032    // ********************************************************************************************
033    // ********************************************************************************************
034    // Class Header Stuff
035    // ********************************************************************************************
036    // ********************************************************************************************
037
038
039    // No Pubic Constructors
040    private PerformanceTimeline () { }
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 : PerformanceTimeline.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        { "eventTypes", });
082    }
083
084
085    // ********************************************************************************************
086    // ********************************************************************************************
087    // Types - Static Inner Classes
088    // ********************************************************************************************
089    // ********************************************************************************************
090
091    /** See https://github.com/WICG/LargestContentfulPaint and largest_contentful_paint.idl */
092    public static class LargestContentfulPaint
093        extends BaseType
094        implements java.io.Serializable
095    {
096        /** For Object Serialization.  java.io.Serializable */
097        protected static final long serialVersionUID = 1;
098        
099        public boolean[] optionals()
100        { return new boolean[] { false, false, false, true, true, true, }; }
101        
102        /** <CODE>[No Description Provided by Google]</CODE> */
103        public final Number renderTime;
104        
105        /** <CODE>[No Description Provided by Google]</CODE> */
106        public final Number loadTime;
107        
108        /** The number of pixels being painted. */
109        public final Number size;
110        
111        /**
112         * The id attribute of the element, if available.
113         * <BR />
114         * <BR /><B>OPTIONAL</B>
115         */
116        public final String elementId;
117        
118        /**
119         * The URL of the image (may be trimmed).
120         * <BR />
121         * <BR /><B>OPTIONAL</B>
122         */
123        public final String url;
124        
125        /**
126         * <CODE>[No Description Provided by Google]</CODE>
127         * <BR />
128         * <BR /><B>OPTIONAL</B>
129         */
130        public final Integer nodeId;
131        
132        /**
133         * Constructor
134         *
135         * @param renderTime -
136         * 
137         * @param loadTime -
138         * 
139         * @param size The number of pixels being painted.
140         * 
141         * @param elementId The id attribute of the element, if available.
142         * <BR /><B>OPTIONAL</B>
143         * 
144         * @param url The URL of the image (may be trimmed).
145         * <BR /><B>OPTIONAL</B>
146         * 
147         * @param nodeId -
148         * <BR /><B>OPTIONAL</B>
149         */
150        public LargestContentfulPaint(
151                Number renderTime, Number loadTime, Number size, String elementId, String url, 
152                Integer nodeId
153            )
154        {
155            // Exception-Check(s) to ensure that if any parameters which are not declared as
156            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
157            
158            if (renderTime == null) BRDPC.throwNPE("renderTime");
159            if (loadTime == null)   BRDPC.throwNPE("loadTime");
160            if (size == null)       BRDPC.throwNPE("size");
161            
162            this.renderTime  = renderTime;
163            this.loadTime    = loadTime;
164            this.size        = size;
165            this.elementId   = elementId;
166            this.url         = url;
167            this.nodeId      = nodeId;
168        }
169        
170        /**
171         * JSON Object Constructor
172         * @param jo A Json-Object having data about an instance of {@code 'LargestContentfulPaint'}.
173         */
174        public LargestContentfulPaint (JsonObject jo)
175        {
176            this.renderTime  = ReadNumberJSON.get(jo, "renderTime", false, true);
177            this.loadTime    = ReadNumberJSON.get(jo, "loadTime", false, true);
178            this.size        = ReadNumberJSON.get(jo, "size", false, true);
179            this.elementId   = ReadJSON.getString(jo, "elementId", true, false);
180            this.url         = ReadJSON.getString(jo, "url", true, false);
181            this.nodeId      = ReadBoxedJSON.getInteger(jo, "nodeId", true);
182        }
183        
184        
185        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
186        public boolean equals(Object other)
187        {
188            if (other == null)                       return false;
189            if (other.getClass() != this.getClass()) return false;
190        
191            LargestContentfulPaint o = (LargestContentfulPaint) other;
192        
193            return
194                    Objects.equals(this.renderTime, o.renderTime)
195                &&  Objects.equals(this.loadTime, o.loadTime)
196                &&  Objects.equals(this.size, o.size)
197                &&  Objects.equals(this.elementId, o.elementId)
198                &&  Objects.equals(this.url, o.url)
199                &&  Objects.equals(this.nodeId, o.nodeId);
200        }
201        
202        /** Generates a Hash-Code for {@code 'this'} instance */
203        public int hashCode()
204        {
205            return
206                    Objects.hashCode(this.renderTime)
207                +   Objects.hashCode(this.loadTime)
208                +   Objects.hashCode(this.size)
209                +   Objects.hashCode(this.elementId)
210                +   Objects.hashCode(this.url)
211                +   Objects.hashCode(this.nodeId);
212        }
213    }
214    
215    /** <CODE>[No Description Provided by Google]</CODE> */
216    public static class LayoutShiftAttribution
217        extends BaseType
218        implements java.io.Serializable
219    {
220        /** For Object Serialization.  java.io.Serializable */
221        protected static final long serialVersionUID = 1;
222        
223        public boolean[] optionals()
224        { return new boolean[] { false, false, true, }; }
225        
226        /** <CODE>[No Description Provided by Google]</CODE> */
227        public final DOM.Rect previousRect;
228        
229        /** <CODE>[No Description Provided by Google]</CODE> */
230        public final DOM.Rect currentRect;
231        
232        /**
233         * <CODE>[No Description Provided by Google]</CODE>
234         * <BR />
235         * <BR /><B>OPTIONAL</B>
236         */
237        public final Integer nodeId;
238        
239        /**
240         * Constructor
241         *
242         * @param previousRect -
243         * 
244         * @param currentRect -
245         * 
246         * @param nodeId -
247         * <BR /><B>OPTIONAL</B>
248         */
249        public LayoutShiftAttribution
250            (DOM.Rect previousRect, DOM.Rect currentRect, Integer nodeId)
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 (previousRect == null) BRDPC.throwNPE("previousRect");
256            if (currentRect == null)  BRDPC.throwNPE("currentRect");
257            
258            this.previousRect  = previousRect;
259            this.currentRect   = currentRect;
260            this.nodeId        = nodeId;
261        }
262        
263        /**
264         * JSON Object Constructor
265         * @param jo A Json-Object having data about an instance of {@code 'LayoutShiftAttribution'}.
266         */
267        public LayoutShiftAttribution (JsonObject jo)
268        {
269            this.previousRect  = ReadJSON.getObject(jo, "previousRect", DOM.Rect.class, false, true);
270            this.currentRect   = ReadJSON.getObject(jo, "currentRect", DOM.Rect.class, false, true);
271            this.nodeId        = ReadBoxedJSON.getInteger(jo, "nodeId", true);
272        }
273        
274        
275        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
276        public boolean equals(Object other)
277        {
278            if (other == null)                       return false;
279            if (other.getClass() != this.getClass()) return false;
280        
281            LayoutShiftAttribution o = (LayoutShiftAttribution) other;
282        
283            return
284                    Objects.equals(this.previousRect, o.previousRect)
285                &&  Objects.equals(this.currentRect, o.currentRect)
286                &&  Objects.equals(this.nodeId, o.nodeId);
287        }
288        
289        /** Generates a Hash-Code for {@code 'this'} instance */
290        public int hashCode()
291        {
292            return
293                    this.previousRect.hashCode()
294                +   this.currentRect.hashCode()
295                +   Objects.hashCode(this.nodeId);
296        }
297    }
298    
299    /** See https://wicg.github.io/layout-instability/#sec-layout-shift and layout_shift.idl */
300    public static class LayoutShift
301        extends BaseType
302        implements java.io.Serializable
303    {
304        /** For Object Serialization.  java.io.Serializable */
305        protected static final long serialVersionUID = 1;
306        
307        public boolean[] optionals()
308        { return new boolean[] { false, false, false, false, }; }
309        
310        /** Score increment produced by this event. */
311        public final Number value;
312        
313        /** <CODE>[No Description Provided by Google]</CODE> */
314        public final boolean hadRecentInput;
315        
316        /** <CODE>[No Description Provided by Google]</CODE> */
317        public final Number lastInputTime;
318        
319        /** <CODE>[No Description Provided by Google]</CODE> */
320        public final PerformanceTimeline.LayoutShiftAttribution[] sources;
321        
322        /**
323         * Constructor
324         *
325         * @param value Score increment produced by this event.
326         * 
327         * @param hadRecentInput -
328         * 
329         * @param lastInputTime -
330         * 
331         * @param sources -
332         */
333        public LayoutShift(
334                Number value, boolean hadRecentInput, Number lastInputTime, 
335                PerformanceTimeline.LayoutShiftAttribution[] sources
336            )
337        {
338            // Exception-Check(s) to ensure that if any parameters which are not declared as
339            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
340            
341            if (value == null)         BRDPC.throwNPE("value");
342            if (lastInputTime == null) BRDPC.throwNPE("lastInputTime");
343            if (sources == null)       BRDPC.throwNPE("sources");
344            
345            this.value           = value;
346            this.hadRecentInput  = hadRecentInput;
347            this.lastInputTime   = lastInputTime;
348            this.sources         = sources;
349        }
350        
351        /**
352         * JSON Object Constructor
353         * @param jo A Json-Object having data about an instance of {@code 'LayoutShift'}.
354         */
355        public LayoutShift (JsonObject jo)
356        {
357            this.value           = ReadNumberJSON.get(jo, "value", false, true);
358            this.hadRecentInput  = ReadPrimJSON.getBoolean(jo, "hadRecentInput");
359            this.lastInputTime   = ReadNumberJSON.get(jo, "lastInputTime", false, true);
360            this.sources = (jo.getJsonArray("sources") == null)
361                ? null
362                : ReadArrJSON.DimN.objArr(jo.getJsonArray("sources"), null, 0, PerformanceTimeline.LayoutShiftAttribution[].class);
363        
364        }
365        
366        
367        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
368        public boolean equals(Object other)
369        {
370            if (other == null)                       return false;
371            if (other.getClass() != this.getClass()) return false;
372        
373            LayoutShift o = (LayoutShift) other;
374        
375            return
376                    Objects.equals(this.value, o.value)
377                &&  (this.hadRecentInput == o.hadRecentInput)
378                &&  Objects.equals(this.lastInputTime, o.lastInputTime)
379                &&  Arrays.deepEquals(this.sources, o.sources);
380        }
381        
382        /** Generates a Hash-Code for {@code 'this'} instance */
383        public int hashCode()
384        {
385            return
386                    Objects.hashCode(this.value)
387                +   (this.hadRecentInput ? 1 : 0)
388                +   Objects.hashCode(this.lastInputTime)
389                +   Arrays.deepHashCode(this.sources);
390        }
391    }
392    
393    /** <CODE>[No Description Provided by Google]</CODE> */
394    public static class TimelineEvent
395        extends BaseType
396        implements java.io.Serializable
397    {
398        /** For Object Serialization.  java.io.Serializable */
399        protected static final long serialVersionUID = 1;
400        
401        public boolean[] optionals()
402        { return new boolean[] { false, false, false, false, true, true, true, }; }
403        
404        /** Identifies the frame that this event is related to. Empty for non-frame targets. */
405        public final String frameId;
406        
407        /**
408         * The event type, as specified in https://w3c.github.io/performance-timeline/#dom-performanceentry-entrytype
409         * This determines which of the optional "details" fiedls is present.
410         */
411        public final String type;
412        
413        /** Name may be empty depending on the type. */
414        public final String name;
415        
416        /** Time in seconds since Epoch, monotonically increasing within document lifetime. */
417        public final Number time;
418        
419        /**
420         * Event duration, if applicable.
421         * <BR />
422         * <BR /><B>OPTIONAL</B>
423         */
424        public final Number duration;
425        
426        /**
427         * <CODE>[No Description Provided by Google]</CODE>
428         * <BR />
429         * <BR /><B>OPTIONAL</B>
430         */
431        public final PerformanceTimeline.LargestContentfulPaint lcpDetails;
432        
433        /**
434         * <CODE>[No Description Provided by Google]</CODE>
435         * <BR />
436         * <BR /><B>OPTIONAL</B>
437         */
438        public final PerformanceTimeline.LayoutShift layoutShiftDetails;
439        
440        /**
441         * Constructor
442         *
443         * @param frameId Identifies the frame that this event is related to. Empty for non-frame targets.
444         * 
445         * @param type 
446         * The event type, as specified in https://w3c.github.io/performance-timeline/#dom-performanceentry-entrytype
447         * This determines which of the optional "details" fiedls is present.
448         * 
449         * @param name Name may be empty depending on the type.
450         * 
451         * @param time Time in seconds since Epoch, monotonically increasing within document lifetime.
452         * 
453         * @param duration Event duration, if applicable.
454         * <BR /><B>OPTIONAL</B>
455         * 
456         * @param lcpDetails -
457         * <BR /><B>OPTIONAL</B>
458         * 
459         * @param layoutShiftDetails -
460         * <BR /><B>OPTIONAL</B>
461         */
462        public TimelineEvent(
463                String frameId, String type, String name, Number time, Number duration, 
464                PerformanceTimeline.LargestContentfulPaint lcpDetails, 
465                PerformanceTimeline.LayoutShift layoutShiftDetails
466            )
467        {
468            // Exception-Check(s) to ensure that if any parameters which are not declared as
469            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
470            
471            if (frameId == null) BRDPC.throwNPE("frameId");
472            if (type == null)    BRDPC.throwNPE("type");
473            if (name == null)    BRDPC.throwNPE("name");
474            if (time == null)    BRDPC.throwNPE("time");
475            
476            this.frameId             = frameId;
477            this.type                = type;
478            this.name                = name;
479            this.time                = time;
480            this.duration            = duration;
481            this.lcpDetails          = lcpDetails;
482            this.layoutShiftDetails  = layoutShiftDetails;
483        }
484        
485        /**
486         * JSON Object Constructor
487         * @param jo A Json-Object having data about an instance of {@code 'TimelineEvent'}.
488         */
489        public TimelineEvent (JsonObject jo)
490        {
491            this.frameId             = ReadJSON.getString(jo, "frameId", false, true);
492            this.type                = ReadJSON.getString(jo, "type", false, true);
493            this.name                = ReadJSON.getString(jo, "name", false, true);
494            this.time                = ReadNumberJSON.get(jo, "time", false, true);
495            this.duration            = ReadNumberJSON.get(jo, "duration", true, false);
496            this.lcpDetails          = ReadJSON.getObject(jo, "lcpDetails", PerformanceTimeline.LargestContentfulPaint.class, true, false);
497            this.layoutShiftDetails  = ReadJSON.getObject(jo, "layoutShiftDetails", PerformanceTimeline.LayoutShift.class, true, false);
498        }
499        
500        
501        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
502        public boolean equals(Object other)
503        {
504            if (other == null)                       return false;
505            if (other.getClass() != this.getClass()) return false;
506        
507            TimelineEvent o = (TimelineEvent) other;
508        
509            return
510                    Objects.equals(this.frameId, o.frameId)
511                &&  Objects.equals(this.type, o.type)
512                &&  Objects.equals(this.name, o.name)
513                &&  Objects.equals(this.time, o.time)
514                &&  Objects.equals(this.duration, o.duration)
515                &&  Objects.equals(this.lcpDetails, o.lcpDetails)
516                &&  Objects.equals(this.layoutShiftDetails, o.layoutShiftDetails);
517        }
518        
519        /** Generates a Hash-Code for {@code 'this'} instance */
520        public int hashCode()
521        {
522            return
523                    Objects.hashCode(this.frameId)
524                +   Objects.hashCode(this.type)
525                +   Objects.hashCode(this.name)
526                +   Objects.hashCode(this.time)
527                +   Objects.hashCode(this.duration)
528                +   this.lcpDetails.hashCode()
529                +   this.layoutShiftDetails.hashCode();
530        }
531    }
532    
533    /** Sent when a performance timeline event is added. See reportPerformanceTimeline method. */
534    public static class timelineEventAdded
535        extends BrowserEvent
536        implements java.io.Serializable
537    {
538        /** For Object Serialization.  java.io.Serializable */
539        protected static final long serialVersionUID = 1;
540        
541        public boolean[] optionals()
542        { return new boolean[] { false, }; }
543        
544        /** <CODE>[No Description Provided by Google]</CODE> */
545        public final PerformanceTimeline.TimelineEvent event;
546        
547        /**
548         * Constructor
549         *
550         * @param event -
551         */
552        public timelineEventAdded(PerformanceTimeline.TimelineEvent event)
553        {
554            super("PerformanceTimeline", "timelineEventAdded", 1);
555            
556            // Exception-Check(s) to ensure that if any parameters which are not declared as
557            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
558            
559            if (event == null) BRDPC.throwNPE("event");
560            
561            this.event  = event;
562        }
563        
564        /**
565         * JSON Object Constructor
566         * @param jo A Json-Object having data about an instance of {@code 'timelineEventAdded'}.
567         */
568        public timelineEventAdded (JsonObject jo)
569        {
570            super("PerformanceTimeline", "timelineEventAdded", 1);
571        
572            this.event  = ReadJSON.getObject(jo, "event", PerformanceTimeline.TimelineEvent.class, false, true);
573        }
574        
575        
576        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
577        public boolean equals(Object other)
578        {
579            if (other == null)                       return false;
580            if (other.getClass() != this.getClass()) return false;
581        
582            timelineEventAdded o = (timelineEventAdded) other;
583        
584            return
585                    Objects.equals(this.event, o.event);
586        }
587        
588        /** Generates a Hash-Code for {@code 'this'} instance */
589        public int hashCode()
590        {
591            return
592                    this.event.hashCode();
593        }
594    }
595    
596    
597    // Counter for keeping the WebSocket Request ID's distinct.
598    private static int counter = 1;
599    
600    /**
601     * Previously buffered events would be reported before method returns.
602     * See also: timelineEventAdded
603     * 
604     * @param eventTypes 
605     * The types of event to report, as specified in
606     * https://w3c.github.io/performance-timeline/#dom-performanceentry-entrytype
607     * The specified filter overrides any previous filters, passing empty
608     * filter disables recording.
609     * Note that not all types exposed to the web platform are currently supported.
610     * 
611     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
612     * {@link Ret0}&gt;</CODE>
613     *
614     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
615     * browser receives the invocation-request.
616     *
617     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
618     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
619     * {@code >} to ensure the Browser Function has run to completion.
620     */
621    public static Script<String, JsonObject, Ret0> enable(String[] eventTypes)
622    {
623        // Exception-Check(s) to ensure that if any parameters which are not declared as
624        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
625        
626        if (eventTypes == null) BRDPC.throwNPE("eventTypes");
627        
628        final int       webSocketID = 34000000 + counter++;
629        final boolean[] optionals   = { false, };
630        
631        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
632        String requestJSON = WriteJSON.get(
633            parameterTypes.get("enable"),
634            parameterNames.get("enable"),
635            optionals, webSocketID,
636            "PerformanceTimeline.enable",
637            (Object) eventTypes
638        );
639        
640        // This Remote Command does not have a Return-Value.
641        return new Script<>
642            (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues);
643    }
644    
645}