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