001package Torello.Browser;
002
003import java.util.*;
004import javax.json.*;
005import javax.json.stream.*;
006import java.io.*;
007
008import java.lang.reflect.Method;
009import java.lang.reflect.Parameter;
010import java.util.function.Function;
011
012import Torello.Java.Additional.*;
013import Torello.Java.JSON.*;
014
015import static Torello.Java.JSON.JFlag.*;
016
017import Torello.Java.StrCmpr;
018import Torello.JavaDoc.StaticFunctional;
019import Torello.JavaDoc.JDHeaderBackgroundImg;
020import Torello.JavaDoc.Excuse;
021
022/**
023 * <SPAN CLASS=COPIEDJDK><B><CODE>[No Description Provided by Google]</CODE></B></SPAN>
024 * 
025 * <EMBED CLASS='external-html' DATA-FILE-ID=CODE_GEN_NOTE>
026 */
027@StaticFunctional(Excused={"counter"}, Excuses={Excuse.CONFIGURATION})
028@JDHeaderBackgroundImg(EmbedTagFileID="WOOD_PLANK_NOTE")
029public class Performance
030{
031    // ********************************************************************************************
032    // ********************************************************************************************
033    // Class Header Stuff
034    // ********************************************************************************************
035    // ********************************************************************************************
036
037
038    // No Pubic Constructors
039    private Performance () { }
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 : Performance.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        parameterNames.put("disable", EMPTY_VEC_STR);
078
079        v = new Vector<String>(1);
080        parameterNames.put("enable", v);
081        Collections.addAll(v, new String[]
082        { "timeDomain", });
083
084        v = new Vector<String>(1);
085        parameterNames.put("setTimeDomain", v);
086        Collections.addAll(v, new String[]
087        { "timeDomain", });
088
089        parameterNames.put("getMetrics", EMPTY_VEC_STR);
090    }
091
092
093    // ********************************************************************************************
094    // ********************************************************************************************
095    // Types - Static Inner Classes
096    // ********************************************************************************************
097    // ********************************************************************************************
098
099    /** Run-time execution metric. */
100    public static class Metric
101        extends BaseType
102        implements java.io.Serializable
103    {
104        /** For Object Serialization.  java.io.Serializable */
105        protected static final long serialVersionUID = 1;
106        
107        public boolean[] optionals()
108        { return new boolean[] { false, false, }; }
109        
110        /** Metric name. */
111        public final String name;
112        
113        /** Metric value. */
114        public final Number value;
115        
116        /**
117         * Constructor
118         *
119         * @param name Metric name.
120         * 
121         * @param value Metric value.
122         */
123        public Metric(String name, Number value)
124        {
125            // Exception-Check(s) to ensure that if any parameters which are not declared as
126            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
127            
128            if (name == null)  THROWS.throwNPE("name");
129            if (value == null) THROWS.throwNPE("value");
130            
131            this.name   = name;
132            this.value  = value;
133        }
134        
135        /**
136         * JSON Object Constructor
137         * @param jo A Json-Object having data about an instance of {@code 'Metric'}.
138         */
139        public Metric (JsonObject jo)
140        {
141            this.name   = ReadJSON.getString(jo, "name", false, true);
142            this.value  = ReadNumberJSON.get(jo, "value", false, true);
143        }
144        
145        
146        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
147        public boolean equals(Object other)
148        {
149            if (this == other)                       return true;
150            if (other == null)                       return false;
151            if (other.getClass() != this.getClass()) return false;
152        
153            Metric o = (Metric) other;
154        
155            return
156                    Objects.equals(this.name, o.name)
157                &&  Objects.equals(this.value, o.value);
158        }
159        
160        /** Generates a Hash-Code for {@code 'this'} instance */
161        public int hashCode()
162        {
163            return
164                    Objects.hashCode(this.name)
165                +   Objects.hashCode(this.value);
166        }
167    }
168    
169    /** Current values of the metrics. */
170    public static class metrics
171        extends BrowserEvent
172        implements java.io.Serializable
173    {
174        /** For Object Serialization.  java.io.Serializable */
175        protected static final long serialVersionUID = 1;
176        
177        public boolean[] optionals()
178        { return new boolean[] { false, false, }; }
179        
180        /** Current values of the metrics. */
181        public final Performance.Metric[] metrics;
182        
183        /** Timestamp title. */
184        public final String title;
185        
186        /**
187         * Constructor
188         *
189         * @param metrics Current values of the metrics.
190         * 
191         * @param title Timestamp title.
192         */
193        public metrics(Performance.Metric[] metrics, String title)
194        {
195            super("Performance", "metrics", 2);
196            
197            // Exception-Check(s) to ensure that if any parameters which are not declared as
198            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
199            
200            if (metrics == null) THROWS.throwNPE("metrics");
201            if (title == null)   THROWS.throwNPE("title");
202            
203            this.metrics  = metrics;
204            this.title    = title;
205        }
206        
207        /**
208         * JSON Object Constructor
209         * @param jo A Json-Object having data about an instance of {@code 'metrics'}.
210         */
211        public metrics (JsonObject jo)
212        {
213            super("Performance", "metrics", 2);
214        
215            this.metrics = (jo.getJsonArray("metrics") == null)
216                ? null
217                : RJArrIntoStream.objArr(jo.getJsonArray("metrics"), null, 0, Performance.Metric.class).toArray(Performance.Metric[]::new);
218        
219            this.title    = ReadJSON.getString(jo, "title", false, true);
220        }
221        
222        
223        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
224        public boolean equals(Object other)
225        {
226            if (this == other)                       return true;
227            if (other == null)                       return false;
228            if (other.getClass() != this.getClass()) return false;
229        
230            metrics o = (metrics) other;
231        
232            return
233                    Arrays.deepEquals(this.metrics, o.metrics)
234                &&  Objects.equals(this.title, o.title);
235        }
236        
237        /** Generates a Hash-Code for {@code 'this'} instance */
238        public int hashCode()
239        {
240            return
241                    Arrays.deepHashCode(this.metrics)
242                +   Objects.hashCode(this.title);
243        }
244    }
245    
246    
247    // Counter for keeping the WebSocket Request ID's distinct.
248    private static int counter = 1;
249    
250    /**
251     * Disable collecting and reporting metrics.
252     * 
253     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
254     * {@link Ret0}&gt;</CODE>
255     *
256     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
257     * browser receives the invocation-request.
258     *
259     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
260     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
261     * {@code >} to ensure the Browser Function has run to completion.
262     */
263    public static Script<String, JsonObject, Ret0> disable()
264    {
265        final int          webSocketID = 33000000 + counter++;
266        final boolean[]    optionals   = new boolean[0];
267        
268        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
269        String requestJSON = WriteJSON.get(
270            parameterTypes.get("disable"),
271            parameterNames.get("disable"),
272            optionals, webSocketID,
273            "Performance.disable"
274        );
275        
276        // This Remote Command does not have a Return-Value.
277        return new Script<>
278            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
279    }
280    
281    /**
282     * Enable collecting and reporting metrics.
283     * 
284     * @param timeDomain Time domain to use for collecting and reporting duration metrics.
285     * <BR />Acceptable Values: ["timeTicks", "threadTicks"]
286     * <BR /><B>OPTIONAL</B>
287     * 
288     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
289     * {@link Ret0}&gt;</CODE>
290     *
291     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
292     * browser receives the invocation-request.
293     *
294     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
295     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
296     * {@code >} to ensure the Browser Function has run to completion.
297     */
298    public static Script<String, JsonObject, Ret0> enable(String timeDomain)
299    {
300        // Exception-Check(s) to ensure that if any parameters which must adhere to a
301        // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
302        
303        THROWS.checkIAE(
304            "timeDomain", timeDomain,
305            "timeTicks", "threadTicks"
306        );
307        
308        final int       webSocketID = 33001000 + counter++;
309        final boolean[] optionals   = { true, };
310        
311        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
312        String requestJSON = WriteJSON.get(
313            parameterTypes.get("enable"),
314            parameterNames.get("enable"),
315            optionals, webSocketID,
316            "Performance.enable",
317            timeDomain
318        );
319        
320        // This Remote Command does not have a Return-Value.
321        return new Script<>
322            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
323    }
324    
325    /**
326     * Sets time domain to use for collecting and reporting duration metrics.
327     * Note that this must be called before enabling metrics collection. Calling
328     * this method while metrics collection is enabled returns an error.
329     * <BR /><B>EXPERIMENTAL</B>
330     * <BR /><B>DEPRECATED</B>
331     * 
332     * @param timeDomain Time domain
333     * <BR />Acceptable Values: ["timeTicks", "threadTicks"]
334     * 
335     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
336     * {@link Ret0}&gt;</CODE>
337     *
338     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
339     * browser receives the invocation-request.
340     *
341     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
342     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
343     * {@code >} to ensure the Browser Function has run to completion.
344     */
345    public static Script<String, JsonObject, Ret0> setTimeDomain(String timeDomain)
346    {
347        // Exception-Check(s) to ensure that if any parameters which are not declared as
348        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
349        
350        if (timeDomain == null) THROWS.throwNPE("timeDomain");
351        
352        // Exception-Check(s) to ensure that if any parameters which must adhere to a
353        // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
354        
355        THROWS.checkIAE(
356            "timeDomain", timeDomain,
357            "timeTicks", "threadTicks"
358        );
359        
360        final int       webSocketID = 33002000 + counter++;
361        final boolean[] optionals   = { false, };
362        
363        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
364        String requestJSON = WriteJSON.get(
365            parameterTypes.get("setTimeDomain"),
366            parameterNames.get("setTimeDomain"),
367            optionals, webSocketID,
368            "Performance.setTimeDomain",
369            timeDomain
370        );
371        
372        // This Remote Command does not have a Return-Value.
373        return new Script<>
374            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
375    }
376    
377    /**
378     * Retrieve current values of run-time metrics.
379     * 
380     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
381     * {@link Performance.Metric}[]&gt;</CODE>
382     * 
383     * <BR /><BR />This <B>script</B> may be <B STYLE='color: red'>executed</B>, using
384     * {@link Script#exec()}, and afterwards, a {@link Promise}<CODE>&lt;JsonObject,
385     * {@link Performance.Metric}[]&gt;</CODE> will be returned.
386     *
387     * <BR /><BR />Finally, the <B>{@code Promise}</B> may be <B STYLE='color: red'>awaited</B>,
388     * using {@link Promise#await()}, <I>and the returned result of this Browser Function may
389      * may be retrieved.</I>
390     *
391     * <BR /><BR />This Browser Function <B STYLE='color: red'>returns</B>
392     * <BR /><BR /><UL CLASS=JDUL>
393     * <LI><CODE>{@link Performance.Metric}[] (<B>metrics</B></CODE>)
394     *     <BR />Current values for run-time metrics.
395     * </LI>
396     * </UL> */
397    public static Script<String, JsonObject, Performance.Metric[]> getMetrics()
398    {
399        final int          webSocketID = 33003000 + counter++;
400        final boolean[]    optionals   = new boolean[0];
401        
402        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
403        String requestJSON = WriteJSON.get(
404            parameterTypes.get("getMetrics"),
405            parameterNames.get("getMetrics"),
406            optionals, webSocketID,
407            "Performance.getMetrics"
408        );
409        
410        // 'JSON Binding' ... Converts Browser Response-JSON to 'Performance.Metric[]'
411        Function<JsonObject, Performance.Metric[]> responseProcessor = (JsonObject jo) ->
412            (jo.getJsonArray("metrics") == null)
413                ? null
414                : RJArrIntoStream.objArr(jo.getJsonArray("metrics"), null, 0, Performance.Metric.class).toArray(Performance.Metric[]::new);
415        
416        return new Script<>(webSocketID, requestJSON, responseProcessor);
417    }
418    
419}