1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484 | package Torello.Browser;
import Torello.JavaDoc.Annotations.IntoHTMLTable;
import static Torello.JavaDoc.Annotations.IntoHTMLTable.Background.BlueDither;
import static Torello.JavaDoc.Annotations.IntoHTMLTable.Background.GreenDither;
import Torello.Browser.JsonAST.PPR;
import Torello.Browser.JsonAST.TypeNode;
import Torello.Java.UnreachableError;
import Torello.Java.ReadOnly.ReadOnlyMap;
import Torello.Java.ReadOnly.ROHashMapBuilder;
import Torello.Java.ReadOnly.ROTreeMapBuilder;
import java.lang.reflect.Field;
import java.util.function.Predicate;
import java.util.regex.Pattern;
// Needed by JavaDoc only (all of the types are used in JavaDoc)
import javax.json.*;
/**
* 💡 Primarily, this class is used by the Code Generator to produce the classes that comprise the
* Java Browser-Automation Library. Generating Java Code to interface with a
* <B STYLE='color:red;'>"Google Compliant Browser"</B> isn't exactly rocket science, but rather it
* is just very tedious and time consuming. When the Code Generator emits a class - that class is
* nothing more than a "wrapper" around a "Web Sockets Implementation" for Google Chromes CDP
* (Chrome DevTools Protocol).
*
* <BR /><BR />
* 🧠The reality is that the entire CDP library is based on nothing more than two JSON files that
* Google has left on a particular Git-Hub Page. You may search Google for the CDP JSON
* specification files, and it will produce a nice page for you. Those JSON files are converted
* <B STYLE='color:red;'><I>piece by piece</I></B> from "Json Strings" into actual Java Types. An
* "AST Tree" is built from the JSON file, and then that AST is passed to a Code Generator that
* "emits" Java Files.
*
* <BR /><BR />
* <B STYLE='color:red'><I>100% of the files in the BrowserAPI & JavaScriptAPI</I></B> were
* produced, themselves, by a Code Generator package that is not actually part of the public
* Torello Java-HTML JAR Distribution Library.
*
* <BR /><BR />
* 📌 This class does nothing more than map a {@code java.lang.String} into a {@code byte} primitive
* constant. Why? Implementing a Code Generator that contains quite a few switch statements which
* "switch" on a Java {@code 'byte'} is much nicer to look at & read than one which is
* repeatedly "switching" on {@code java.lang.String's}.
*
* <BR /><BR />
* 🚫 It's quite simple really! Only downside (for you, the user) is that I don't actually expose
* or provide the Code Generator's Java source code. Sorry, it's just not a useful thing for
* anyone except me! (Trust me, you really wouldn't care...)
*/
@Torello.JavaDoc.Annotations.JDHeaderBackgroundImg(EmbedTagFileID="INTERNAL_USE_JDHBI")
public class CDPTypes
{
private CDPTypes() { }
/**
* <BR>CDP In-Browser Type: An actual Data-Object, defined for use by the browser
* <BR>Web-Sockets Transmisson Layer: The Json-Type {@link JsonObject}
* <BR>Java Type: Any one of the scores of Data-Classes inside the Browser & Java-Script
* API packages. (These are always a 'nested class' of any domain-class)
* <BR>Note: A type that is a "CDP Type" *must* be one of type, event or command-return-types
*/
@IntoHTMLTable(title="Indicates an In-Browser 'Data-Class'", background=BlueDither)
public static final byte CDP_TYPE = 1;
/**
* <BR>CDP In-Browser Type: An array of Browser Types / Objects
* <BR>Web-Sockets Transmisson Layer: The Json-Type {@link JsonArray}
* <BR>Java Type: An array of a 'nested-class' data-object
*/
@IntoHTMLTable(title="An Array of any one In-Browser 'Data-Class'", background=GreenDither)
public static final byte CDP_TYPE_ARRAY_1D = CDP_TYPE + 1;
/**
* <BR>CDP In-Browser Type: Unknown, Any
* <BR>Web-Sockets Transmisson Layer: The Json-Type Raw-Json
* <BR>Java Type: {@link JsonObject}
* <BR>Note: There are *VERY FEW* types which are defined as 'Any' or (unknown) 'Object' in
* Google's CDP Spec-Files. When it used, you (the user) get to receive the "Raw
* JSON Object" that was transmitted via Web-Socket.
*/
@IntoHTMLTable(title="Unspecified Browser Type - Accepts Any Type!", background=BlueDither)
public static final byte RAW_JSON_VALUE = CDP_TYPE_ARRAY_1D + 1;
// ********************************************************************************************
// ********************************************************************************************
// Some Basic-Types
// ********************************************************************************************
// ********************************************************************************************
/**
* <BR>CDP In-Browser Type: Integer
* <BR>Web-Sockets Transmisson Layer: The Json-Type {@link JsonNumber}
* <BR>Java Type: Primitive {@code 'int'}
*/
@IntoHTMLTable(title="Required, Non-Nullable 'int'", background=GreenDither)
public static final byte PRIMITIVE_INT = RAW_JSON_VALUE + 1;
/**
* <BR>CDP In-Browser Type: Integer
* <BR>Web-Sockets Transmisson Layer: The Json-Type {@link JsonNumber}
* <BR>Java Type: Boxed-Type {@code java.lang.Integer}
*/
@IntoHTMLTable(title="Nullabele / Optional Integer", background=BlueDither)
public static final byte BOXED_INTEGER = PRIMITIVE_INT + 1;
/**
* <BR>CDP In-Browser Type: Boolean
* <BR>Web-Sockets Transmisson Layer: Either {@link JsonValue#TRUE} or {@link JsonValue#FALSE}
* <BR>Java Type: Primitive {@code 'boolean'}
*/
@IntoHTMLTable(title="Required, Non-Nullable boolean", background=GreenDither)
public static final byte PRIMITIVE_BOOLEAN = BOXED_INTEGER + 1;
/**
* <BR>CDP In-Browser Type: Boolean
* <BR>Web-Sockets Transmisson Layer: Either {@link JsonValue#TRUE} or {@link JsonValue#FALSE}
* <BR>Java Type: Boxed-Type {@code java.lang.Boolean}
*/
@IntoHTMLTable(title="Optional / Nullable boolean", background=BlueDither)
public static final byte BOXED_BOOLEAN = PRIMITIVE_BOOLEAN + 1;
/**
* <BR>CDP In-Browser Type: String
* <BR>Web-Sockets Transmisson Layer: The Json-Type {@link JsonString}
* <BR>Java Type: A {@code java.lang.String}
*/
@IntoHTMLTable(title="String of Characters", background=GreenDither)
public static final byte STRING = BOXED_BOOLEAN + 1;
/**
* <BR>CDP In-Browser Type: Unspecified numeric type
* <BR>Web-Sockets Transmisson Layer: The Json-Type {@link JsonNumber}
* <BR>Java Type: Any concrete sub-class of {@code java.lang.Number}
*/
@IntoHTMLTable(title="Unspecified Numeric Type", background=BlueDither)
public static final byte NUMBER = STRING + 1;
// ********************************************************************************************
// ********************************************************************************************
// One-Dimensional Array-Types
// ********************************************************************************************
// ********************************************************************************************
/**
* <BR>CDP In-Browser Type: One dimensional integer array
* <BR>Web-Sockets Transmisson Layer: The Json-Type {@link JsonArray}
* <BR>Expectation: It is <B STYLE='color:red;'><I>expected</I></B> that input
* {@link JsonArray} instances have only valid integers, and no
* {@link JsonValue#NULL Json Null's}
* <BR>Java Type: Primitive {@code int[]}-Array
*/
@IntoHTMLTable(title="Type: int[]-Array", background=GreenDither)
public static final byte INT_ARRAY_1D = NUMBER + 1;
/**
* <BR>CDP In-Browser Type: One dimensional boolean array
* <BR>Web-Sockets Transmisson Layer: The Json-Type {@link JsonArray}
* <BR>Expectation: It is <B STYLE='color:red;'><I>expected</I></B> that input
* {@link JsonArray} instances contain only {@link JsonValue#TRUE} or {@link JsonValue#FALSE},
* without any {@link JsonValue#NULL Json Null's}
* <BR>Java Type: Primitive {@code boolean[]}-Array
*/
@IntoHTMLTable(title="Type: boolean[]-Array", background=BlueDither)
public static final byte BOOLEAN_ARRAY_1D = INT_ARRAY_1D + 1;
/**
* <BR>CDP In-Browser Type: One dimensional string array
* <BR>Web-Sockets Transmisson Layer: The Json-Type {@link JsonArray}
* <BR>Expectation: It is <B STYLE='color:red;'><I>expected</I></B> that the {@link JsonArray}
* have only valid {@link JsonString} instances
* <BR>Java Type: A {@code java.lang.String[]}
*/
@IntoHTMLTable(title="Type: String[]-Array", background=GreenDither)
public static final byte STRING_ARRAY_1D = BOOLEAN_ARRAY_1D + 1;
/**
* <BR>CDP In-Browser Type: One dimensional numeric array, of an unspecified numeric type
* <BR>Web-Sockets Transmisson Layer: The Json-Type {@link JsonArray}
* <BR>Java Type: A {@code Number[]} (may contain any concrete {@code java.lang.Number} subclass)
*/
@IntoHTMLTable(title="Type: Number[]-Array", background=BlueDither)
public static final byte NUMBER_ARRAY_1D = STRING_ARRAY_1D + 1;
// ********************************************************************************************
// ********************************************************************************************
// Two-Dimensional Array-Types
// ********************************************************************************************
// ********************************************************************************************
/**
* <BR>CDP In-Browser Type: Two-dimensional integer array
* <BR>Web-Sockets Transmisson Layer: The Json-Type {@link JsonArray}
* <BR>Expectation: It is <B STYLE='color:red;'><I>expected</I></B> that the {@link JsonArray}
* be a valid 2-D array of arrays.
* <BR>Java Type: Primitive, two-dimensioinal {@code int[][]}-Array
*/
@IntoHTMLTable(title="Type: 2-D int[][]-Array", background=GreenDither)
public static final byte INT_ARRAY_2D = NUMBER_ARRAY_1D + 1;
/**
* <BR>CDP In-Browser Type: Two dimensional boolean array
* <BR>Web-Sockets Transmisson Layer: The Json-Type {@link JsonArray}
* <BR>Expectation: It is <B STYLE='color:red;'><I>expected</I></B> that the {@link JsonArray}
* be a valid 2-D array of arrays.
* <BR>Java Type: Primitive, two-dimensioinal {@code boolean[][]}-Array
*/
@IntoHTMLTable(title="Type: 2-D boolean[][]-Array", background=BlueDither)
public static final byte BOOLEAN_ARRAY_2D = INT_ARRAY_2D + 1;
/**
* <BR>CDP In-Browser Type: Two dimensional string array
* <BR>Web-Sockets Transmisson Layer: The Json-Type {@link JsonArray}
* <BR>Expectation: It is <B STYLE='color:red;'><I>expected</I></B> that the {@link JsonArray}
* be a valid 2-D array of arrays.
* <BR>Java Type: Two-dimensional {@code String[][]}-Array
*/
@IntoHTMLTable(title="Type: 2-D String[][]-Array", background=GreenDither)
public static final byte STRING_ARRAY_2D = BOOLEAN_ARRAY_2D + 1;
/**
* <BR>CDP In-Browser Type: Two dimensional numeric array, of an unspecified numeric type
* <BR>Web-Sockets Transmisson Layer: The Json-Type {@link JsonArray}
* <BR>Expectation: It is <B STYLE='color:red;'><I>expected</I></B> that the {@link JsonArray}
* be a valid 2-D array of arrays.
* <BR>Java Type: Two-dimensional {@code Number[][]}-Array
*/
@IntoHTMLTable(title="Type: 2-D Number[][] Array", background=BlueDither)
public static final byte NUMBER_ARRAY_2D = STRING_ARRAY_2D + 1;
// ********************************************************************************************
// ********************************************************************************************
// Byte to "Name as a Java String" (A simple "ReadOnlyMap" of Byte -> String)
// ********************************************************************************************
// ********************************************************************************************
/**
* The "switch" from a number to string is done using this map. When a Code Generator "emits"
* or "outputs" (when it does its thing, and generates Java Source Code), it literally just
* goes through the AST and using lots of {@code java.lang.StringBuilder} to build strings.
*
* <BR /><BR />
* The {@code String's} which are produced, are saved directly to {@code '.java'} files, and
* eventually those {@code '.java'} files are compiled using the standard {@code 'javac'}
* compiler stage of the Torello Build-Tool, and turned into the {@code '.class'} files offered
* by the Java-HTML JAR Library.
*
* <BR /><BR /><DIV CLASS=JDHint>
* Click on the "View Hilited Source" arrow-button '⮫' (directly above) to see how this map
* is loaded, using reflection.
*
* <BR /><BR />
* This particular field does nothing more than map one of the {@code 'byte'} constants, such
* as {@link #PRIMITIVE_INT} or {@link #NUMBER_ARRAY_1D} to the Java {@code 'String'} name of
* that constant - {@code "PRIMITIVE_INT"} or {@code "NUMBER_ARRAY_1D"}.
* </DIV>
*
* <BR /><DIV CLASS=JDHintAlt>
* If you ask "Why?" - again, the classes inside {@code 'BrowserAPI'} and
* {@code 'JavaScriptAPI'} have source code that was emitted,
* <B STYLE='color:red'><I>automatically</B></I>, and "emitting" Java Code such as
* {@code "CDPTypes.PRIMTIVIE_INT"} requires this little map field.
*
* <BR ><BR />
* It is that simple, but unfortunately, the Java Code Generator which produces the classes in
* this API is not part of the public-API, and therefore its source code cannot be viewed. It
* mostly "really boring" stuff. The code generator isn't included in the Java-HTML
* {@code '.jar'} because it doesn't serve any purpose, other than generating the
* {@code '.java'} files inside {@code 'BrowserAPI'} and {@code 'JavaScriptAPI'}.
* </DIV>
*/
public static final ReadOnlyMap<Byte, String> names;
static
{
final Field[] fArr = CDPTypes.class.getFields();
final ROHashMapBuilder<Byte, String> rohmb = new ROHashMapBuilder<>();
try
{
for (final Field f : fArr)
// Only save the static-byte fields within this class! Remember, there are a few
// fields which are not actually "byte constants". Skip any field which isn't one
// of the byte constants at the top of this class.
//
// Map-Key: The actual byte-value of the constant (1, 2, 3....)
// Map-Value: The actual name of the constant "PRIMITIVE_INT",
// "BOOLEAN_ARRAY_1D" etc.
if (f.getType() == byte.class)
rohmb.put((byte) f.getInt(null), f.getName());
}
// This should just never happen, because I only declare "public byte" fields. All fields
// which are "byte" are "public", so IllegalAccessError should be, theoretically, perfectly
// impossible!
//
// NOTE: 'IllegalAccessException' is a checked exception, and "UnreachableError" inherits
// java.lang.Error, and is therefore, unchecked.
catch (IllegalAccessException iae) { throw new UnreachableError(iae); }
names = rohmb.build();
}
// ********************************************************************************************
// ********************************************************************************************
// Java-String to "Byte"
// ********************************************************************************************
// ********************************************************************************************
// This is used inside of the two methods, below. It serves no purpose whatsoever outside of
// this class. This class is largely an "internal use only", or a "non-public facing API"
// class. The only problems with Java's keyword "public" is that sometimes there are classes
// which have to be "public", due to the fact that their methods & fields are used outside of
// the package in which they are defined.
//
// This class is used over & over outside of the package 'Torello.Browser' - where it is
// defined. However, actual end-users, themselves, ought never find a need for using it!
private static final ReadOnlyMap<String, Byte> bytes;
static
{
final ROTreeMapBuilder<String, Byte> rotmb = new ROTreeMapBuilder<>();
rotmb.put("JsonValue", RAW_JSON_VALUE);
rotmb.put("int", PRIMITIVE_INT);
rotmb.put("Integer", BOXED_INTEGER);
rotmb.put("boolean", PRIMITIVE_BOOLEAN);
rotmb.put("Boolean", BOXED_BOOLEAN);
rotmb.put("String", STRING);
rotmb.put("Number", NUMBER);
rotmb.put("int[]", INT_ARRAY_1D);
rotmb.put("boolean[]", BOOLEAN_ARRAY_1D);
rotmb.put("String[]", STRING_ARRAY_1D);
rotmb.put("Number[]", NUMBER_ARRAY_1D);
rotmb.put("int[][]", INT_ARRAY_2D);
rotmb.put("boolean[][]", BOOLEAN_ARRAY_2D);
rotmb.put("String[][]", STRING_ARRAY_2D);
rotmb.put("Number[][]", NUMBER_ARRAY_2D);
bytes = rotmb.build();
}
// CD types obey this rule - all it says is that things like "Accessibility.AXNode" is a
// match. Any class-name (as a string) which is a "nested class" of some other class will
// produce a "match" by this predicate.
private static final Predicate<String> CDP_TYPE_NAME_PREDICATE =
Pattern.compile("\\w+\\.\\w+").asPredicate();
/**
* Converts the strings created inside the Json-AST package into a {@code 'byte'} constant
*
* <BR /><BR /><DIV CLASS=JDHint>
* Note that there is one minor "exceptional case" that is handled inside of this method.
* Just look at the test for {@code FilterEntry[]}, below, to see how it is handled. It's a
* minor nuisance inside of the CDP specs.
* </DIV>
*
* <BR /><BR /><DIV CLASS=JDHintAlt>
* This class is used only once, throughout all of the Java-HTML {@code '.jar'}. It may be
* found inside the AST node for "types" (see class {@link TypeNode}). Click on the
* {@code TypeNode} link, and then click the "View Hilited Source" to see this method's use.
*
* <BR /><BR />
* It may found inside the package-private constructor for that class.
* </DIV>
*
* @param CTAS The "Computed Type as a String"
*
* @return A {@code 'byte'} constant which represents that type. If the type is an actual
* and reified browser object type, then the {@code 'byte'} constants {@link #CDP_TYPE} or
* {@link #CDP_TYPE_ARRAY_1D} are returned instead.
*
* @throws UnrecognizedCTASError
* <EMBED CLASS='external-html' DATA-FILE-ID=CDPTypes.UnrecognizedCTASError>
*
* @see TypeNode
*/
public static byte ctasToByte(final String CTAS)
{
final Byte ret = bytes.get(CTAS);
if (ret != null) return ret.byteValue();
else if (CTAS.equals("FilterEntry[]")) return CDP_TYPE_ARRAY_1D;
else if (CDP_TYPE_NAME_PREDICATE.test(CTAS)) return CDP_TYPE;
else throw new UnrecognizedCTASError(CTAS);
}
/**
* Converts the strings created inside the Json-AST package into a {@code 'byte'} constant
*
* <BR /><BR /><DIV CLASS=JDHint>
* This class is used only once throughout all of the Java-HTML {@code '.jar'}. It may be
* found inside the AST node for "Parameters, Properties & Return-Values" ({@link PPR}).
* Click the PPR link, and then click the "View Hilited Source" to see this method's use.
*
* <BR /><BR />
* It may be found inside the package-private method named "setCTAS(String)"
* </DIV>
*
* @param CTAS The "Computed Type as a String"
* @param refNonNull indicates whether the {@link PPR#reference()} returns null
* @param refArrayNonNull indicates whether the {@link PPR#referenceArray()} returns null
*
* @return A {@code 'byte'} constant which represents that type. If the type is an actual
* and reified browser object type, then the {@code 'byte'} constants {@link #CDP_TYPE} or
* {@link #CDP_TYPE_ARRAY_1D} are returned instead.
*
* @throws UnrecognizedCTASError
* <EMBED CLASS='external-html' DATA-FILE-ID=CDPTypes.UnrecognizedCTASError>
*
* @see PPR
*/
public static byte ctasToByte
(final String CTAS, final boolean refNonNull, final boolean refArrayNonNull)
{
final Byte ret = bytes.get(CTAS);
if (ret != null) return ret.byteValue();
else if (refNonNull) return CDP_TYPE;
else if (refArrayNonNull) return CDP_TYPE_ARRAY_1D;
else throw new UnrecognizedCTASError(CTAS);
}
// ********************************************************************************************
// ********************************************************************************************
// Byte to Java Type-As-String
// ********************************************************************************************
// ********************************************************************************************
/** Switches from a {@code byte} constant to the Java-Type, as a {@code java.lang.String} */
public static final ReadOnlyMap<Byte, String> types;
static
{
final ROTreeMapBuilder<Byte, String> rotmb = new ROTreeMapBuilder<>();
rotmb.put(RAW_JSON_VALUE, "JsonValue");
rotmb.put(PRIMITIVE_INT, "int");
rotmb.put(BOXED_INTEGER, "Integer");
rotmb.put(PRIMITIVE_BOOLEAN, "boolean");
rotmb.put(BOXED_BOOLEAN, "Boolean");
rotmb.put(STRING, "String");
rotmb.put(NUMBER, "Number");
rotmb.put(INT_ARRAY_1D, "int[]");
rotmb.put(BOOLEAN_ARRAY_1D, "boolean[]");
rotmb.put(STRING_ARRAY_1D, "String[]");
rotmb.put(NUMBER_ARRAY_1D, "Number[]");
rotmb.put(INT_ARRAY_2D, "int[][]");
rotmb.put(BOOLEAN_ARRAY_2D, "boolean[][]");
rotmb.put(STRING_ARRAY_2D, "String[][]");
rotmb.put(NUMBER_ARRAY_2D, "Number[][]");
types = rotmb.build();
}
}
|