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)  BRDPC.throwNPE("name");
129            if (value == null) BRDPC.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 (other == null)                       return false;
150            if (other.getClass() != this.getClass()) return false;
151        
152            Metric o = (Metric) other;
153        
154            return
155                    Objects.equals(this.name, o.name)
156                &&  Objects.equals(this.value, o.value);
157        }
158        
159        /** Generates a Hash-Code for {@code 'this'} instance */
160        public int hashCode()
161        {
162            return
163                    Objects.hashCode(this.name)
164                +   Objects.hashCode(this.value);
165        }
166    }
167    
168    /** Current values of the metrics. */
169    public static class metrics
170        extends BrowserEvent
171        implements java.io.Serializable
172    {
173        /** For Object Serialization.  java.io.Serializable */
174        protected static final long serialVersionUID = 1;
175        
176        public boolean[] optionals()
177        { return new boolean[] { false, false, }; }
178        
179        /** Current values of the metrics. */
180        public final Performance.Metric[] metrics;
181        
182        /** Timestamp title. */
183        public final String title;
184        
185        /**
186         * Constructor
187         *
188         * @param metrics Current values of the metrics.
189         * 
190         * @param title Timestamp title.
191         */
192        public metrics(Performance.Metric[] metrics, String title)
193        {
194            super("Performance", "metrics", 2);
195            
196            // Exception-Check(s) to ensure that if any parameters which are not declared as
197            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
198            
199            if (metrics == null) BRDPC.throwNPE("metrics");
200            if (title == null)   BRDPC.throwNPE("title");
201            
202            this.metrics  = metrics;
203            this.title    = title;
204        }
205        
206        /**
207         * JSON Object Constructor
208         * @param jo A Json-Object having data about an instance of {@code 'metrics'}.
209         */
210        public metrics (JsonObject jo)
211        {
212            super("Performance", "metrics", 2);
213        
214            this.metrics = (jo.getJsonArray("metrics") == null)
215                ? null
216                : ReadArrJSON.DimN.objArr(jo.getJsonArray("metrics"), null, 0, Performance.Metric[].class);
217        
218            this.title    = ReadJSON.getString(jo, "title", false, true);
219        }
220        
221        
222        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
223        public boolean equals(Object other)
224        {
225            if (other == null)                       return false;
226            if (other.getClass() != this.getClass()) return false;
227        
228            metrics o = (metrics) other;
229        
230            return
231                    Arrays.deepEquals(this.metrics, o.metrics)
232                &&  Objects.equals(this.title, o.title);
233        }
234        
235        /** Generates a Hash-Code for {@code 'this'} instance */
236        public int hashCode()
237        {
238            return
239                    Arrays.deepHashCode(this.metrics)
240                +   Objects.hashCode(this.title);
241        }
242    }
243    
244    
245    // Counter for keeping the WebSocket Request ID's distinct.
246    private static int counter = 1;
247    
248    /**
249     * Disable collecting and reporting metrics.
250     * 
251     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
252     * {@link Ret0}&gt;</CODE>
253     *
254     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
255     * browser receives the invocation-request.
256     *
257     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
258     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
259     * {@code >} to ensure the Browser Function has run to completion.
260     */
261    public static Script<String, JsonObject, Ret0> disable()
262    {
263        final int          webSocketID = 33000000 + counter++;
264        final boolean[]    optionals   = new boolean[0];
265        
266        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
267        String requestJSON = WriteJSON.get(
268            parameterTypes.get("disable"),
269            parameterNames.get("disable"),
270            optionals, webSocketID,
271            "Performance.disable"
272        );
273        
274        // This Remote Command does not have a Return-Value.
275        return new Script<>
276            (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues);
277    }
278    
279    /**
280     * Enable collecting and reporting metrics.
281     * 
282     * @param timeDomain Time domain to use for collecting and reporting duration metrics.
283     * <BR />Acceptable Values: ["timeTicks", "threadTicks"]
284     * <BR /><B>OPTIONAL</B>
285     * 
286     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
287     * {@link Ret0}&gt;</CODE>
288     *
289     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
290     * browser receives the invocation-request.
291     *
292     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
293     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
294     * {@code >} to ensure the Browser Function has run to completion.
295     */
296    public static Script<String, JsonObject, Ret0> enable(String timeDomain)
297    {
298        // Exception-Check(s) to ensure that if any parameters which must adhere to a
299        // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
300        
301        BRDPC.checkIAE(
302            "timeDomain", timeDomain,
303            "timeTicks", "threadTicks"
304        );
305        
306        final int       webSocketID = 33001000 + counter++;
307        final boolean[] optionals   = { true, };
308        
309        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
310        String requestJSON = WriteJSON.get(
311            parameterTypes.get("enable"),
312            parameterNames.get("enable"),
313            optionals, webSocketID,
314            "Performance.enable",
315            timeDomain
316        );
317        
318        // This Remote Command does not have a Return-Value.
319        return new Script<>
320            (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues);
321    }
322    
323    /**
324     * Sets time domain to use for collecting and reporting duration metrics.
325     * Note that this must be called before enabling metrics collection. Calling
326     * this method while metrics collection is enabled returns an error.
327     * <BR /><B>EXPERIMENTAL</B>
328     * <BR /><B>DEPRECATED</B>
329     * 
330     * @param timeDomain Time domain
331     * <BR />Acceptable Values: ["timeTicks", "threadTicks"]
332     * 
333     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
334     * {@link Ret0}&gt;</CODE>
335     *
336     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
337     * browser receives the invocation-request.
338     *
339     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
340     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
341     * {@code >} to ensure the Browser Function has run to completion.
342     */
343    public static Script<String, JsonObject, Ret0> setTimeDomain(String timeDomain)
344    {
345        // Exception-Check(s) to ensure that if any parameters which are not declared as
346        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
347        
348        if (timeDomain == null) BRDPC.throwNPE("timeDomain");
349        
350        // Exception-Check(s) to ensure that if any parameters which must adhere to a
351        // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
352        
353        BRDPC.checkIAE(
354            "timeDomain", timeDomain,
355            "timeTicks", "threadTicks"
356        );
357        
358        final int       webSocketID = 33002000 + counter++;
359        final boolean[] optionals   = { false, };
360        
361        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
362        String requestJSON = WriteJSON.get(
363            parameterTypes.get("setTimeDomain"),
364            parameterNames.get("setTimeDomain"),
365            optionals, webSocketID,
366            "Performance.setTimeDomain",
367            timeDomain
368        );
369        
370        // This Remote Command does not have a Return-Value.
371        return new Script<>
372            (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues);
373    }
374    
375    /**
376     * Retrieve current values of run-time metrics.
377     * 
378     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
379     * {@link Performance.Metric}[]&gt;</CODE>
380     * 
381     * <BR /><BR />This <B>script</B> may be <B STYLE='color: red'>executed</B>, using
382     * {@link Script#exec()}, and afterwards, a {@link Promise}<CODE>&lt;JsonObject,
383     * {@link Performance.Metric}[]&gt;</CODE> will be returned.
384     *
385     * <BR /><BR />Finally, the <B>{@code Promise}</B> may be <B STYLE='color: red'>awaited</B>,
386     * using {@link Promise#await()}, <I>and the returned result of this Browser Function may
387      * may be retrieved.</I>
388     *
389     * <BR /><BR />This Browser Function <B STYLE='color: red'>returns</B>
390     * <BR /><BR /><UL CLASS=JDUL>
391     * <LI><CODE>{@link Performance.Metric}[] (<B>metrics</B></CODE>)
392     *     <BR />Current values for run-time metrics.
393     * </LI>
394     * </UL> */
395    public static Script<String, JsonObject, Performance.Metric[]> getMetrics()
396    {
397        final int          webSocketID = 33003000 + counter++;
398        final boolean[]    optionals   = new boolean[0];
399        
400        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
401        String requestJSON = WriteJSON.get(
402            parameterTypes.get("getMetrics"),
403            parameterNames.get("getMetrics"),
404            optionals, webSocketID,
405            "Performance.getMetrics"
406        );
407        
408        // 'JSON Binding' ... Converts Browser Response-JSON to 'Performance.Metric[]'
409        Function<JsonObject, Performance.Metric[]> responseProcessor = (JsonObject jo) ->
410            (jo.getJsonArray("metrics") == null)
411                ? null
412                : ReadArrJSON.DimN.objArr(jo.getJsonArray("metrics"), null, 0, Performance.Metric[].class);
413        
414        // Pass the 'defaultSender' to Script-Constructor
415        // The sender that is used can be changed before executing script.
416        return new Script<>(BRDPC.defaultSender, webSocketID, requestJSON, responseProcessor);
417    }
418    
419}