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>This domain facilitates obtaining document snapshots with DOM, layout, and style information.</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 DOMSnapshot
030{
031    // ********************************************************************************************
032    // ********************************************************************************************
033    // Class Header Stuff
034    // ********************************************************************************************
035    // ********************************************************************************************
036
037
038    // No Pubic Constructors
039    private DOMSnapshot () { }
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 : DOMSnapshot.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        parameterNames.put("enable", EMPTY_VEC_STR);
080
081        v = new Vector<String>(4);
082        parameterNames.put("getSnapshot", v);
083        Collections.addAll(v, new String[]
084        { "computedStyleWhitelist", "includeEventListeners", "includePaintOrder", "includeUserAgentShadowTree", });
085
086        v = new Vector<String>(5);
087        parameterNames.put("captureSnapshot", v);
088        Collections.addAll(v, new String[]
089        { "computedStyles", "includePaintOrder", "includeDOMRects", "includeBlendedBackgroundColors", "includeTextColorOpacities", });
090    }
091
092
093    // ********************************************************************************************
094    // ********************************************************************************************
095    // Types - Static Inner Classes
096    // ********************************************************************************************
097    // ********************************************************************************************
098
099    // public static class StringIndex => Integer
100    
101    // public static class ArrayOfStrings => int[]
102    
103    // public static class Rectangle => Number[]
104    
105    /** A Node in the DOM tree. */
106    public static class DOMNode
107        extends BaseType
108        implements java.io.Serializable
109    {
110        /** For Object Serialization.  java.io.Serializable */
111        protected static final long serialVersionUID = 1;
112        
113        public boolean[] optionals()
114        { return new boolean[] { false, false, false, true, true, true, true, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, }; }
115        
116        /** <CODE>Node</CODE>'s nodeType. */
117        public final int nodeType;
118        
119        /** <CODE>Node</CODE>'s nodeName. */
120        public final String nodeName;
121        
122        /** <CODE>Node</CODE>'s nodeValue. */
123        public final String nodeValue;
124        
125        /**
126         * Only set for textarea elements, contains the text value.
127         * <BR />
128         * <BR /><B>OPTIONAL</B>
129         */
130        public final String textValue;
131        
132        /**
133         * Only set for input elements, contains the input's associated text value.
134         * <BR />
135         * <BR /><B>OPTIONAL</B>
136         */
137        public final String inputValue;
138        
139        /**
140         * Only set for radio and checkbox input elements, indicates if the element has been checked
141         * <BR />
142         * <BR /><B>OPTIONAL</B>
143         */
144        public final Boolean inputChecked;
145        
146        /**
147         * Only set for option elements, indicates if the element has been selected
148         * <BR />
149         * <BR /><B>OPTIONAL</B>
150         */
151        public final Boolean optionSelected;
152        
153        /** <CODE>Node</CODE>'s id, corresponds to DOM.Node.backendNodeId. */
154        public final int backendNodeId;
155        
156        /**
157         * The indexes of the node's child nodes in the <CODE>domNodes</CODE> array returned by <CODE>getSnapshot</CODE>, if
158         * any.
159         * <BR />
160         * <BR /><B>OPTIONAL</B>
161         */
162        public final int[] childNodeIndexes;
163        
164        /**
165         * Attributes of an <CODE>Element</CODE> node.
166         * <BR />
167         * <BR /><B>OPTIONAL</B>
168         */
169        public final DOMSnapshot.NameValue[] attributes;
170        
171        /**
172         * Indexes of pseudo elements associated with this node in the <CODE>domNodes</CODE> array returned by
173         * <CODE>getSnapshot</CODE>, if any.
174         * <BR />
175         * <BR /><B>OPTIONAL</B>
176         */
177        public final int[] pseudoElementIndexes;
178        
179        /**
180         * The index of the node's related layout tree node in the <CODE>layoutTreeNodes</CODE> array returned by
181         * <CODE>getSnapshot</CODE>, if any.
182         * <BR />
183         * <BR /><B>OPTIONAL</B>
184         */
185        public final Integer layoutNodeIndex;
186        
187        /**
188         * Document URL that <CODE>Document</CODE> or <CODE>FrameOwner</CODE> node points to.
189         * <BR />
190         * <BR /><B>OPTIONAL</B>
191         */
192        public final String documentURL;
193        
194        /**
195         * Base URL that <CODE>Document</CODE> or <CODE>FrameOwner</CODE> node uses for URL completion.
196         * <BR />
197         * <BR /><B>OPTIONAL</B>
198         */
199        public final String baseURL;
200        
201        /**
202         * Only set for documents, contains the document's content language.
203         * <BR />
204         * <BR /><B>OPTIONAL</B>
205         */
206        public final String contentLanguage;
207        
208        /**
209         * Only set for documents, contains the document's character set encoding.
210         * <BR />
211         * <BR /><B>OPTIONAL</B>
212         */
213        public final String documentEncoding;
214        
215        /**
216         * <CODE>DocumentType</CODE> node's publicId.
217         * <BR />
218         * <BR /><B>OPTIONAL</B>
219         */
220        public final String publicId;
221        
222        /**
223         * <CODE>DocumentType</CODE> node's systemId.
224         * <BR />
225         * <BR /><B>OPTIONAL</B>
226         */
227        public final String systemId;
228        
229        /**
230         * Frame ID for frame owner elements and also for the document node.
231         * <BR />
232         * <BR /><B>OPTIONAL</B>
233         */
234        public final String frameId;
235        
236        /**
237         * The index of a frame owner element's content document in the <CODE>domNodes</CODE> array returned by
238         * <CODE>getSnapshot</CODE>, if any.
239         * <BR />
240         * <BR /><B>OPTIONAL</B>
241         */
242        public final Integer contentDocumentIndex;
243        
244        /**
245         * Type of a pseudo element node.
246         * <BR />
247         * <BR /><B>OPTIONAL</B>
248         */
249        public final String pseudoType;
250        
251        /**
252         * Shadow root type.
253         * <BR />
254         * <BR /><B>OPTIONAL</B>
255         */
256        public final String shadowRootType;
257        
258        /**
259         * Whether this DOM node responds to mouse clicks. This includes nodes that have had click
260         * event listeners attached via JavaScript as well as anchor tags that naturally navigate when
261         * clicked.
262         * <BR />
263         * <BR /><B>OPTIONAL</B>
264         */
265        public final Boolean isClickable;
266        
267        /**
268         * Details of the node's event listeners, if any.
269         * <BR />
270         * <BR /><B>OPTIONAL</B>
271         */
272        public final DOMDebugger.EventListener[] eventListeners;
273        
274        /**
275         * The selected url for nodes with a srcset attribute.
276         * <BR />
277         * <BR /><B>OPTIONAL</B>
278         */
279        public final String currentSourceURL;
280        
281        /**
282         * The url of the script (if any) that generates this node.
283         * <BR />
284         * <BR /><B>OPTIONAL</B>
285         */
286        public final String originURL;
287        
288        /**
289         * Scroll offsets, set when this node is a Document.
290         * <BR />
291         * <BR /><B>OPTIONAL</B>
292         */
293        public final Number scrollOffsetX;
294        
295        /**
296         * <CODE>[No Description Provided by Google]</CODE>
297         * <BR />
298         * <BR /><B>OPTIONAL</B>
299         */
300        public final Number scrollOffsetY;
301        
302        /**
303         * Constructor
304         *
305         * @param nodeType <CODE>Node</CODE>'s nodeType.
306         * 
307         * @param nodeName <CODE>Node</CODE>'s nodeName.
308         * 
309         * @param nodeValue <CODE>Node</CODE>'s nodeValue.
310         * 
311         * @param textValue Only set for textarea elements, contains the text value.
312         * <BR /><B>OPTIONAL</B>
313         * 
314         * @param inputValue Only set for input elements, contains the input's associated text value.
315         * <BR /><B>OPTIONAL</B>
316         * 
317         * @param inputChecked Only set for radio and checkbox input elements, indicates if the element has been checked
318         * <BR /><B>OPTIONAL</B>
319         * 
320         * @param optionSelected Only set for option elements, indicates if the element has been selected
321         * <BR /><B>OPTIONAL</B>
322         * 
323         * @param backendNodeId <CODE>Node</CODE>'s id, corresponds to DOM.Node.backendNodeId.
324         * 
325         * @param childNodeIndexes 
326         * The indexes of the node's child nodes in the <CODE>domNodes</CODE> array returned by <CODE>getSnapshot</CODE>, if
327         * any.
328         * <BR /><B>OPTIONAL</B>
329         * 
330         * @param attributes Attributes of an <CODE>Element</CODE> node.
331         * <BR /><B>OPTIONAL</B>
332         * 
333         * @param pseudoElementIndexes 
334         * Indexes of pseudo elements associated with this node in the <CODE>domNodes</CODE> array returned by
335         * <CODE>getSnapshot</CODE>, if any.
336         * <BR /><B>OPTIONAL</B>
337         * 
338         * @param layoutNodeIndex 
339         * The index of the node's related layout tree node in the <CODE>layoutTreeNodes</CODE> array returned by
340         * <CODE>getSnapshot</CODE>, if any.
341         * <BR /><B>OPTIONAL</B>
342         * 
343         * @param documentURL Document URL that <CODE>Document</CODE> or <CODE>FrameOwner</CODE> node points to.
344         * <BR /><B>OPTIONAL</B>
345         * 
346         * @param baseURL Base URL that <CODE>Document</CODE> or <CODE>FrameOwner</CODE> node uses for URL completion.
347         * <BR /><B>OPTIONAL</B>
348         * 
349         * @param contentLanguage Only set for documents, contains the document's content language.
350         * <BR /><B>OPTIONAL</B>
351         * 
352         * @param documentEncoding Only set for documents, contains the document's character set encoding.
353         * <BR /><B>OPTIONAL</B>
354         * 
355         * @param publicId <CODE>DocumentType</CODE> node's publicId.
356         * <BR /><B>OPTIONAL</B>
357         * 
358         * @param systemId <CODE>DocumentType</CODE> node's systemId.
359         * <BR /><B>OPTIONAL</B>
360         * 
361         * @param frameId Frame ID for frame owner elements and also for the document node.
362         * <BR /><B>OPTIONAL</B>
363         * 
364         * @param contentDocumentIndex 
365         * The index of a frame owner element's content document in the <CODE>domNodes</CODE> array returned by
366         * <CODE>getSnapshot</CODE>, if any.
367         * <BR /><B>OPTIONAL</B>
368         * 
369         * @param pseudoType Type of a pseudo element node.
370         * <BR /><B>OPTIONAL</B>
371         * 
372         * @param shadowRootType Shadow root type.
373         * <BR /><B>OPTIONAL</B>
374         * 
375         * @param isClickable 
376         * Whether this DOM node responds to mouse clicks. This includes nodes that have had click
377         * event listeners attached via JavaScript as well as anchor tags that naturally navigate when
378         * clicked.
379         * <BR /><B>OPTIONAL</B>
380         * 
381         * @param eventListeners Details of the node's event listeners, if any.
382         * <BR /><B>OPTIONAL</B>
383         * 
384         * @param currentSourceURL The selected url for nodes with a srcset attribute.
385         * <BR /><B>OPTIONAL</B>
386         * 
387         * @param originURL The url of the script (if any) that generates this node.
388         * <BR /><B>OPTIONAL</B>
389         * 
390         * @param scrollOffsetX Scroll offsets, set when this node is a Document.
391         * <BR /><B>OPTIONAL</B>
392         * 
393         * @param scrollOffsetY -
394         * <BR /><B>OPTIONAL</B>
395         */
396        public DOMNode(
397                int nodeType, String nodeName, String nodeValue, String textValue, 
398                String inputValue, Boolean inputChecked, Boolean optionSelected, int backendNodeId, 
399                int[] childNodeIndexes, DOMSnapshot.NameValue[] attributes, 
400                int[] pseudoElementIndexes, Integer layoutNodeIndex, String documentURL, 
401                String baseURL, String contentLanguage, String documentEncoding, String publicId, 
402                String systemId, String frameId, Integer contentDocumentIndex, String pseudoType, 
403                String shadowRootType, Boolean isClickable, 
404                DOMDebugger.EventListener[] eventListeners, String currentSourceURL, 
405                String originURL, Number scrollOffsetX, Number scrollOffsetY
406            )
407        {
408            // Exception-Check(s) to ensure that if any parameters which are not declared as
409            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
410            
411            if (nodeName == null)  THROWS.throwNPE("nodeName");
412            if (nodeValue == null) THROWS.throwNPE("nodeValue");
413            
414            // Exception-Check(s) to ensure that if any parameters which must adhere to a
415            // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw.
416            
417            THROWS.checkIAE("pseudoType", pseudoType, "DOM.PseudoType", DOM.PseudoType);
418            THROWS.checkIAE("shadowRootType", shadowRootType, "DOM.ShadowRootType", DOM.ShadowRootType);
419            
420            this.nodeType              = nodeType;
421            this.nodeName              = nodeName;
422            this.nodeValue             = nodeValue;
423            this.textValue             = textValue;
424            this.inputValue            = inputValue;
425            this.inputChecked          = inputChecked;
426            this.optionSelected        = optionSelected;
427            this.backendNodeId         = backendNodeId;
428            this.childNodeIndexes      = childNodeIndexes;
429            this.attributes            = attributes;
430            this.pseudoElementIndexes  = pseudoElementIndexes;
431            this.layoutNodeIndex       = layoutNodeIndex;
432            this.documentURL           = documentURL;
433            this.baseURL               = baseURL;
434            this.contentLanguage       = contentLanguage;
435            this.documentEncoding      = documentEncoding;
436            this.publicId              = publicId;
437            this.systemId              = systemId;
438            this.frameId               = frameId;
439            this.contentDocumentIndex  = contentDocumentIndex;
440            this.pseudoType            = pseudoType;
441            this.shadowRootType        = shadowRootType;
442            this.isClickable           = isClickable;
443            this.eventListeners        = eventListeners;
444            this.currentSourceURL      = currentSourceURL;
445            this.originURL             = originURL;
446            this.scrollOffsetX         = scrollOffsetX;
447            this.scrollOffsetY         = scrollOffsetY;
448        }
449        
450        /**
451         * JSON Object Constructor
452         * @param jo A Json-Object having data about an instance of {@code 'DOMNode'}.
453         */
454        public DOMNode (JsonObject jo)
455        {
456            this.nodeType              = ReadPrimJSON.getInt(jo, "nodeType");
457            this.nodeName              = ReadJSON.getString(jo, "nodeName", false, true);
458            this.nodeValue             = ReadJSON.getString(jo, "nodeValue", false, true);
459            this.textValue             = ReadJSON.getString(jo, "textValue", true, false);
460            this.inputValue            = ReadJSON.getString(jo, "inputValue", true, false);
461            this.inputChecked          = ReadBoxedJSON.getBoolean(jo, "inputChecked", true);
462            this.optionSelected        = ReadBoxedJSON.getBoolean(jo, "optionSelected", true);
463            this.backendNodeId         = ReadPrimJSON.getInt(jo, "backendNodeId");
464            this.childNodeIndexes = (jo.getJsonArray("childNodeIndexes") == null)
465                ? null
466                : RJArrIntoPrimArray.intArr(jo.getJsonArray("childNodeIndexes"), -1, 0, null);
467        
468            this.attributes = (jo.getJsonArray("attributes") == null)
469                ? null
470                : RJArrIntoStream.objArr(jo.getJsonArray("attributes"), null, 0, DOMSnapshot.NameValue.class).toArray(DOMSnapshot.NameValue[]::new);
471        
472            this.pseudoElementIndexes = (jo.getJsonArray("pseudoElementIndexes") == null)
473                ? null
474                : RJArrIntoPrimArray.intArr(jo.getJsonArray("pseudoElementIndexes"), -1, 0, null);
475        
476            this.layoutNodeIndex       = ReadBoxedJSON.getInteger(jo, "layoutNodeIndex", true);
477            this.documentURL           = ReadJSON.getString(jo, "documentURL", true, false);
478            this.baseURL               = ReadJSON.getString(jo, "baseURL", true, false);
479            this.contentLanguage       = ReadJSON.getString(jo, "contentLanguage", true, false);
480            this.documentEncoding      = ReadJSON.getString(jo, "documentEncoding", true, false);
481            this.publicId              = ReadJSON.getString(jo, "publicId", true, false);
482            this.systemId              = ReadJSON.getString(jo, "systemId", true, false);
483            this.frameId               = ReadJSON.getString(jo, "frameId", true, false);
484            this.contentDocumentIndex  = ReadBoxedJSON.getInteger(jo, "contentDocumentIndex", true);
485            this.pseudoType            = ReadJSON.getString(jo, "pseudoType", true, false);
486            this.shadowRootType        = ReadJSON.getString(jo, "shadowRootType", true, false);
487            this.isClickable           = ReadBoxedJSON.getBoolean(jo, "isClickable", true);
488            this.eventListeners = (jo.getJsonArray("eventListeners") == null)
489                ? null
490                : RJArrIntoStream.objArr(jo.getJsonArray("eventListeners"), null, 0, DOMDebugger.EventListener.class).toArray(DOMDebugger.EventListener[]::new);
491        
492            this.currentSourceURL      = ReadJSON.getString(jo, "currentSourceURL", true, false);
493            this.originURL             = ReadJSON.getString(jo, "originURL", true, false);
494            this.scrollOffsetX         = ReadNumberJSON.get(jo, "scrollOffsetX", true, false);
495            this.scrollOffsetY         = ReadNumberJSON.get(jo, "scrollOffsetY", true, false);
496        }
497        
498        
499        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
500        public boolean equals(Object other)
501        {
502            if (this == other)                       return true;
503            if (other == null)                       return false;
504            if (other.getClass() != this.getClass()) return false;
505        
506            DOMNode o = (DOMNode) other;
507        
508            return
509                    (this.nodeType == o.nodeType)
510                &&  Objects.equals(this.nodeName, o.nodeName)
511                &&  Objects.equals(this.nodeValue, o.nodeValue)
512                &&  Objects.equals(this.textValue, o.textValue)
513                &&  Objects.equals(this.inputValue, o.inputValue)
514                &&  Objects.equals(this.inputChecked, o.inputChecked)
515                &&  Objects.equals(this.optionSelected, o.optionSelected)
516                &&  Objects.equals(this.backendNodeId, o.backendNodeId)
517                &&  Arrays.equals(this.childNodeIndexes, o.childNodeIndexes)
518                &&  Arrays.deepEquals(this.attributes, o.attributes)
519                &&  Arrays.equals(this.pseudoElementIndexes, o.pseudoElementIndexes)
520                &&  Objects.equals(this.layoutNodeIndex, o.layoutNodeIndex)
521                &&  Objects.equals(this.documentURL, o.documentURL)
522                &&  Objects.equals(this.baseURL, o.baseURL)
523                &&  Objects.equals(this.contentLanguage, o.contentLanguage)
524                &&  Objects.equals(this.documentEncoding, o.documentEncoding)
525                &&  Objects.equals(this.publicId, o.publicId)
526                &&  Objects.equals(this.systemId, o.systemId)
527                &&  Objects.equals(this.frameId, o.frameId)
528                &&  Objects.equals(this.contentDocumentIndex, o.contentDocumentIndex)
529                &&  Objects.equals(this.pseudoType, o.pseudoType)
530                &&  Objects.equals(this.shadowRootType, o.shadowRootType)
531                &&  Objects.equals(this.isClickable, o.isClickable)
532                &&  Arrays.deepEquals(this.eventListeners, o.eventListeners)
533                &&  Objects.equals(this.currentSourceURL, o.currentSourceURL)
534                &&  Objects.equals(this.originURL, o.originURL)
535                &&  Objects.equals(this.scrollOffsetX, o.scrollOffsetX)
536                &&  Objects.equals(this.scrollOffsetY, o.scrollOffsetY);
537        }
538        
539        /** Generates a Hash-Code for {@code 'this'} instance */
540        public int hashCode()
541        {
542            return
543                    this.nodeType
544                +   Objects.hashCode(this.nodeName)
545                +   Objects.hashCode(this.nodeValue)
546                +   Objects.hashCode(this.textValue)
547                +   Objects.hashCode(this.inputValue)
548                +   Objects.hashCode(this.inputChecked)
549                +   Objects.hashCode(this.optionSelected)
550                +   this.backendNodeId
551                +   Arrays.hashCode(this.childNodeIndexes)
552                +   Arrays.deepHashCode(this.attributes)
553                +   Arrays.hashCode(this.pseudoElementIndexes)
554                +   Objects.hashCode(this.layoutNodeIndex)
555                +   Objects.hashCode(this.documentURL)
556                +   Objects.hashCode(this.baseURL)
557                +   Objects.hashCode(this.contentLanguage)
558                +   Objects.hashCode(this.documentEncoding)
559                +   Objects.hashCode(this.publicId)
560                +   Objects.hashCode(this.systemId)
561                +   Objects.hashCode(this.frameId)
562                +   Objects.hashCode(this.contentDocumentIndex)
563                +   Objects.hashCode(this.pseudoType)
564                +   Objects.hashCode(this.shadowRootType)
565                +   Objects.hashCode(this.isClickable)
566                +   Arrays.deepHashCode(this.eventListeners)
567                +   Objects.hashCode(this.currentSourceURL)
568                +   Objects.hashCode(this.originURL)
569                +   Objects.hashCode(this.scrollOffsetX)
570                +   Objects.hashCode(this.scrollOffsetY);
571        }
572    }
573    
574    /**
575     * Details of post layout rendered text positions. The exact layout should not be regarded as
576     * stable and may change between versions.
577     */
578    public static class InlineTextBox
579        extends BaseType
580        implements java.io.Serializable
581    {
582        /** For Object Serialization.  java.io.Serializable */
583        protected static final long serialVersionUID = 1;
584        
585        public boolean[] optionals()
586        { return new boolean[] { false, false, false, }; }
587        
588        /** The bounding box in document coordinates. Note that scroll offset of the document is ignored. */
589        public final DOM.Rect boundingBox;
590        
591        /**
592         * The starting index in characters, for this post layout textbox substring. Characters that
593         * would be represented as a surrogate pair in UTF-16 have length 2.
594         */
595        public final int startCharacterIndex;
596        
597        /**
598         * The number of characters in this post layout textbox substring. Characters that would be
599         * represented as a surrogate pair in UTF-16 have length 2.
600         */
601        public final int numCharacters;
602        
603        /**
604         * Constructor
605         *
606         * @param boundingBox The bounding box in document coordinates. Note that scroll offset of the document is ignored.
607         * 
608         * @param startCharacterIndex 
609         * The starting index in characters, for this post layout textbox substring. Characters that
610         * would be represented as a surrogate pair in UTF-16 have length 2.
611         * 
612         * @param numCharacters 
613         * The number of characters in this post layout textbox substring. Characters that would be
614         * represented as a surrogate pair in UTF-16 have length 2.
615         */
616        public InlineTextBox(DOM.Rect boundingBox, int startCharacterIndex, int numCharacters)
617        {
618            // Exception-Check(s) to ensure that if any parameters which are not declared as
619            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
620            
621            if (boundingBox == null) THROWS.throwNPE("boundingBox");
622            
623            this.boundingBox          = boundingBox;
624            this.startCharacterIndex  = startCharacterIndex;
625            this.numCharacters        = numCharacters;
626        }
627        
628        /**
629         * JSON Object Constructor
630         * @param jo A Json-Object having data about an instance of {@code 'InlineTextBox'}.
631         */
632        public InlineTextBox (JsonObject jo)
633        {
634            this.boundingBox          = ReadJSON.getObject(jo, "boundingBox", DOM.Rect.class, false, true);
635            this.startCharacterIndex  = ReadPrimJSON.getInt(jo, "startCharacterIndex");
636            this.numCharacters        = ReadPrimJSON.getInt(jo, "numCharacters");
637        }
638        
639        
640        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
641        public boolean equals(Object other)
642        {
643            if (this == other)                       return true;
644            if (other == null)                       return false;
645            if (other.getClass() != this.getClass()) return false;
646        
647            InlineTextBox o = (InlineTextBox) other;
648        
649            return
650                    Objects.equals(this.boundingBox, o.boundingBox)
651                &&  (this.startCharacterIndex == o.startCharacterIndex)
652                &&  (this.numCharacters == o.numCharacters);
653        }
654        
655        /** Generates a Hash-Code for {@code 'this'} instance */
656        public int hashCode()
657        {
658            return
659                    this.boundingBox.hashCode()
660                +   this.startCharacterIndex
661                +   this.numCharacters;
662        }
663    }
664    
665    /** Details of an element in the DOM tree with a LayoutObject. */
666    public static class LayoutTreeNode
667        extends BaseType
668        implements java.io.Serializable
669    {
670        /** For Object Serialization.  java.io.Serializable */
671        protected static final long serialVersionUID = 1;
672        
673        public boolean[] optionals()
674        { return new boolean[] { false, false, true, true, true, true, true, }; }
675        
676        /** The index of the related DOM node in the <CODE>domNodes</CODE> array returned by <CODE>getSnapshot</CODE>. */
677        public final int domNodeIndex;
678        
679        /** The bounding box in document coordinates. Note that scroll offset of the document is ignored. */
680        public final DOM.Rect boundingBox;
681        
682        /**
683         * Contents of the LayoutText, if any.
684         * <BR />
685         * <BR /><B>OPTIONAL</B>
686         */
687        public final String layoutText;
688        
689        /**
690         * The post-layout inline text nodes, if any.
691         * <BR />
692         * <BR /><B>OPTIONAL</B>
693         */
694        public final DOMSnapshot.InlineTextBox[] inlineTextNodes;
695        
696        /**
697         * Index into the <CODE>computedStyles</CODE> array returned by <CODE>getSnapshot</CODE>.
698         * <BR />
699         * <BR /><B>OPTIONAL</B>
700         */
701        public final Integer styleIndex;
702        
703        /**
704         * Global paint order index, which is determined by the stacking order of the nodes. Nodes
705         * that are painted together will have the same index. Only provided if includePaintOrder in
706         * getSnapshot was true.
707         * <BR />
708         * <BR /><B>OPTIONAL</B>
709         */
710        public final Integer paintOrder;
711        
712        /**
713         * Set to true to indicate the element begins a new stacking context.
714         * <BR />
715         * <BR /><B>OPTIONAL</B>
716         */
717        public final Boolean isStackingContext;
718        
719        /**
720         * Constructor
721         *
722         * @param domNodeIndex The index of the related DOM node in the <CODE>domNodes</CODE> array returned by <CODE>getSnapshot</CODE>.
723         * 
724         * @param boundingBox The bounding box in document coordinates. Note that scroll offset of the document is ignored.
725         * 
726         * @param layoutText Contents of the LayoutText, if any.
727         * <BR /><B>OPTIONAL</B>
728         * 
729         * @param inlineTextNodes The post-layout inline text nodes, if any.
730         * <BR /><B>OPTIONAL</B>
731         * 
732         * @param styleIndex Index into the <CODE>computedStyles</CODE> array returned by <CODE>getSnapshot</CODE>.
733         * <BR /><B>OPTIONAL</B>
734         * 
735         * @param paintOrder 
736         * Global paint order index, which is determined by the stacking order of the nodes. Nodes
737         * that are painted together will have the same index. Only provided if includePaintOrder in
738         * getSnapshot was true.
739         * <BR /><B>OPTIONAL</B>
740         * 
741         * @param isStackingContext Set to true to indicate the element begins a new stacking context.
742         * <BR /><B>OPTIONAL</B>
743         */
744        public LayoutTreeNode(
745                int domNodeIndex, DOM.Rect boundingBox, String layoutText, 
746                DOMSnapshot.InlineTextBox[] inlineTextNodes, Integer styleIndex, Integer paintOrder, 
747                Boolean isStackingContext
748            )
749        {
750            // Exception-Check(s) to ensure that if any parameters which are not declared as
751            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
752            
753            if (boundingBox == null) THROWS.throwNPE("boundingBox");
754            
755            this.domNodeIndex       = domNodeIndex;
756            this.boundingBox        = boundingBox;
757            this.layoutText         = layoutText;
758            this.inlineTextNodes    = inlineTextNodes;
759            this.styleIndex         = styleIndex;
760            this.paintOrder         = paintOrder;
761            this.isStackingContext  = isStackingContext;
762        }
763        
764        /**
765         * JSON Object Constructor
766         * @param jo A Json-Object having data about an instance of {@code 'LayoutTreeNode'}.
767         */
768        public LayoutTreeNode (JsonObject jo)
769        {
770            this.domNodeIndex       = ReadPrimJSON.getInt(jo, "domNodeIndex");
771            this.boundingBox        = ReadJSON.getObject(jo, "boundingBox", DOM.Rect.class, false, true);
772            this.layoutText         = ReadJSON.getString(jo, "layoutText", true, false);
773            this.inlineTextNodes = (jo.getJsonArray("inlineTextNodes") == null)
774                ? null
775                : RJArrIntoStream.objArr(jo.getJsonArray("inlineTextNodes"), null, 0, DOMSnapshot.InlineTextBox.class).toArray(DOMSnapshot.InlineTextBox[]::new);
776        
777            this.styleIndex         = ReadBoxedJSON.getInteger(jo, "styleIndex", true);
778            this.paintOrder         = ReadBoxedJSON.getInteger(jo, "paintOrder", true);
779            this.isStackingContext  = ReadBoxedJSON.getBoolean(jo, "isStackingContext", true);
780        }
781        
782        
783        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
784        public boolean equals(Object other)
785        {
786            if (this == other)                       return true;
787            if (other == null)                       return false;
788            if (other.getClass() != this.getClass()) return false;
789        
790            LayoutTreeNode o = (LayoutTreeNode) other;
791        
792            return
793                    (this.domNodeIndex == o.domNodeIndex)
794                &&  Objects.equals(this.boundingBox, o.boundingBox)
795                &&  Objects.equals(this.layoutText, o.layoutText)
796                &&  Arrays.deepEquals(this.inlineTextNodes, o.inlineTextNodes)
797                &&  Objects.equals(this.styleIndex, o.styleIndex)
798                &&  Objects.equals(this.paintOrder, o.paintOrder)
799                &&  Objects.equals(this.isStackingContext, o.isStackingContext);
800        }
801        
802        /** Generates a Hash-Code for {@code 'this'} instance */
803        public int hashCode()
804        {
805            return
806                    this.domNodeIndex
807                +   this.boundingBox.hashCode()
808                +   Objects.hashCode(this.layoutText)
809                +   Arrays.deepHashCode(this.inlineTextNodes)
810                +   Objects.hashCode(this.styleIndex)
811                +   Objects.hashCode(this.paintOrder)
812                +   Objects.hashCode(this.isStackingContext);
813        }
814    }
815    
816    /** A subset of the full ComputedStyle as defined by the request whitelist. */
817    public static class ComputedStyle
818        extends BaseType
819        implements java.io.Serializable
820    {
821        /** For Object Serialization.  java.io.Serializable */
822        protected static final long serialVersionUID = 1;
823        
824        public boolean[] optionals()
825        { return new boolean[] { false, }; }
826        
827        /** Name/value pairs of computed style properties. */
828        public final DOMSnapshot.NameValue[] properties;
829        
830        /**
831         * Constructor
832         *
833         * @param properties Name/value pairs of computed style properties.
834         */
835        public ComputedStyle(DOMSnapshot.NameValue[] properties)
836        {
837            // Exception-Check(s) to ensure that if any parameters which are not declared as
838            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
839            
840            if (properties == null) THROWS.throwNPE("properties");
841            
842            this.properties  = properties;
843        }
844        
845        /**
846         * JSON Object Constructor
847         * @param jo A Json-Object having data about an instance of {@code 'ComputedStyle'}.
848         */
849        public ComputedStyle (JsonObject jo)
850        {
851            this.properties = (jo.getJsonArray("properties") == null)
852                ? null
853                : RJArrIntoStream.objArr(jo.getJsonArray("properties"), null, 0, DOMSnapshot.NameValue.class).toArray(DOMSnapshot.NameValue[]::new);
854        
855        }
856        
857        
858        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
859        public boolean equals(Object other)
860        {
861            if (this == other)                       return true;
862            if (other == null)                       return false;
863            if (other.getClass() != this.getClass()) return false;
864        
865            ComputedStyle o = (ComputedStyle) other;
866        
867            return
868                    Arrays.deepEquals(this.properties, o.properties);
869        }
870        
871        /** Generates a Hash-Code for {@code 'this'} instance */
872        public int hashCode()
873        {
874            return
875                    Arrays.deepHashCode(this.properties);
876        }
877    }
878    
879    /** A name/value pair. */
880    public static class NameValue
881        extends BaseType
882        implements java.io.Serializable
883    {
884        /** For Object Serialization.  java.io.Serializable */
885        protected static final long serialVersionUID = 1;
886        
887        public boolean[] optionals()
888        { return new boolean[] { false, false, }; }
889        
890        /** Attribute/property name. */
891        public final String name;
892        
893        /** Attribute/property value. */
894        public final String value;
895        
896        /**
897         * Constructor
898         *
899         * @param name Attribute/property name.
900         * 
901         * @param value Attribute/property value.
902         */
903        public NameValue(String name, String value)
904        {
905            // Exception-Check(s) to ensure that if any parameters which are not declared as
906            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
907            
908            if (name == null)  THROWS.throwNPE("name");
909            if (value == null) THROWS.throwNPE("value");
910            
911            this.name   = name;
912            this.value  = value;
913        }
914        
915        /**
916         * JSON Object Constructor
917         * @param jo A Json-Object having data about an instance of {@code 'NameValue'}.
918         */
919        public NameValue (JsonObject jo)
920        {
921            this.name   = ReadJSON.getString(jo, "name", false, true);
922            this.value  = ReadJSON.getString(jo, "value", false, true);
923        }
924        
925        
926        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
927        public boolean equals(Object other)
928        {
929            if (this == other)                       return true;
930            if (other == null)                       return false;
931            if (other.getClass() != this.getClass()) return false;
932        
933            NameValue o = (NameValue) other;
934        
935            return
936                    Objects.equals(this.name, o.name)
937                &&  Objects.equals(this.value, o.value);
938        }
939        
940        /** Generates a Hash-Code for {@code 'this'} instance */
941        public int hashCode()
942        {
943            return
944                    Objects.hashCode(this.name)
945                +   Objects.hashCode(this.value);
946        }
947    }
948    
949    /** Data that is only present on rare nodes. */
950    public static class RareStringData
951        extends BaseType
952        implements java.io.Serializable
953    {
954        /** For Object Serialization.  java.io.Serializable */
955        protected static final long serialVersionUID = 1;
956        
957        public boolean[] optionals()
958        { return new boolean[] { false, false, }; }
959        
960        /** <CODE>[No Description Provided by Google]</CODE> */
961        public final int[] index;
962        
963        /** <CODE>[No Description Provided by Google]</CODE> */
964        public final int[] value;
965        
966        /**
967         * Constructor
968         *
969         * @param index -
970         * 
971         * @param value -
972         */
973        public RareStringData(int[] index, int[] value)
974        {
975            // Exception-Check(s) to ensure that if any parameters which are not declared as
976            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
977            
978            if (index == null) THROWS.throwNPE("index");
979            if (value == null) THROWS.throwNPE("value");
980            
981            this.index  = index;
982            this.value  = value;
983        }
984        
985        /**
986         * JSON Object Constructor
987         * @param jo A Json-Object having data about an instance of {@code 'RareStringData'}.
988         */
989        public RareStringData (JsonObject jo)
990        {
991            this.index = (jo.getJsonArray("index") == null)
992                ? null
993                : RJArrIntoPrimArray.intArr(jo.getJsonArray("index"), -1, 0, null);
994        
995            this.value = (jo.getJsonArray("value") == null)
996                ? null
997                : RJArrIntoPrimArray.intArr(jo.getJsonArray("value"), -1, 0, null);
998        
999        }
1000        
1001        
1002        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
1003        public boolean equals(Object other)
1004        {
1005            if (this == other)                       return true;
1006            if (other == null)                       return false;
1007            if (other.getClass() != this.getClass()) return false;
1008        
1009            RareStringData o = (RareStringData) other;
1010        
1011            return
1012                    Arrays.equals(this.index, o.index)
1013                &&  Arrays.equals(this.value, o.value);
1014        }
1015        
1016        /** Generates a Hash-Code for {@code 'this'} instance */
1017        public int hashCode()
1018        {
1019            return
1020                    Arrays.hashCode(this.index)
1021                +   Arrays.hashCode(this.value);
1022        }
1023    }
1024    
1025    /** <CODE>[No Description Provided by Google]</CODE> */
1026    public static class RareBooleanData
1027        extends BaseType
1028        implements java.io.Serializable
1029    {
1030        /** For Object Serialization.  java.io.Serializable */
1031        protected static final long serialVersionUID = 1;
1032        
1033        public boolean[] optionals()
1034        { return new boolean[] { false, }; }
1035        
1036        /** <CODE>[No Description Provided by Google]</CODE> */
1037        public final int[] index;
1038        
1039        /**
1040         * Constructor
1041         *
1042         * @param index -
1043         */
1044        public RareBooleanData(int[] index)
1045        {
1046            // Exception-Check(s) to ensure that if any parameters which are not declared as
1047            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
1048            
1049            if (index == null) THROWS.throwNPE("index");
1050            
1051            this.index  = index;
1052        }
1053        
1054        /**
1055         * JSON Object Constructor
1056         * @param jo A Json-Object having data about an instance of {@code 'RareBooleanData'}.
1057         */
1058        public RareBooleanData (JsonObject jo)
1059        {
1060            this.index = (jo.getJsonArray("index") == null)
1061                ? null
1062                : RJArrIntoPrimArray.intArr(jo.getJsonArray("index"), -1, 0, null);
1063        
1064        }
1065        
1066        
1067        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
1068        public boolean equals(Object other)
1069        {
1070            if (this == other)                       return true;
1071            if (other == null)                       return false;
1072            if (other.getClass() != this.getClass()) return false;
1073        
1074            RareBooleanData o = (RareBooleanData) other;
1075        
1076            return
1077                    Arrays.equals(this.index, o.index);
1078        }
1079        
1080        /** Generates a Hash-Code for {@code 'this'} instance */
1081        public int hashCode()
1082        {
1083            return
1084                    Arrays.hashCode(this.index);
1085        }
1086    }
1087    
1088    /** <CODE>[No Description Provided by Google]</CODE> */
1089    public static class RareIntegerData
1090        extends BaseType
1091        implements java.io.Serializable
1092    {
1093        /** For Object Serialization.  java.io.Serializable */
1094        protected static final long serialVersionUID = 1;
1095        
1096        public boolean[] optionals()
1097        { return new boolean[] { false, false, }; }
1098        
1099        /** <CODE>[No Description Provided by Google]</CODE> */
1100        public final int[] index;
1101        
1102        /** <CODE>[No Description Provided by Google]</CODE> */
1103        public final int[] value;
1104        
1105        /**
1106         * Constructor
1107         *
1108         * @param index -
1109         * 
1110         * @param value -
1111         */
1112        public RareIntegerData(int[] index, int[] value)
1113        {
1114            // Exception-Check(s) to ensure that if any parameters which are not declared as
1115            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
1116            
1117            if (index == null) THROWS.throwNPE("index");
1118            if (value == null) THROWS.throwNPE("value");
1119            
1120            this.index  = index;
1121            this.value  = value;
1122        }
1123        
1124        /**
1125         * JSON Object Constructor
1126         * @param jo A Json-Object having data about an instance of {@code 'RareIntegerData'}.
1127         */
1128        public RareIntegerData (JsonObject jo)
1129        {
1130            this.index = (jo.getJsonArray("index") == null)
1131                ? null
1132                : RJArrIntoPrimArray.intArr(jo.getJsonArray("index"), -1, 0, null);
1133        
1134            this.value = (jo.getJsonArray("value") == null)
1135                ? null
1136                : RJArrIntoPrimArray.intArr(jo.getJsonArray("value"), -1, 0, null);
1137        
1138        }
1139        
1140        
1141        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
1142        public boolean equals(Object other)
1143        {
1144            if (this == other)                       return true;
1145            if (other == null)                       return false;
1146            if (other.getClass() != this.getClass()) return false;
1147        
1148            RareIntegerData o = (RareIntegerData) other;
1149        
1150            return
1151                    Arrays.equals(this.index, o.index)
1152                &&  Arrays.equals(this.value, o.value);
1153        }
1154        
1155        /** Generates a Hash-Code for {@code 'this'} instance */
1156        public int hashCode()
1157        {
1158            return
1159                    Arrays.hashCode(this.index)
1160                +   Arrays.hashCode(this.value);
1161        }
1162    }
1163    
1164    /** Document snapshot. */
1165    public static class DocumentSnapshot
1166        extends BaseType
1167        implements java.io.Serializable
1168    {
1169        /** For Object Serialization.  java.io.Serializable */
1170        protected static final long serialVersionUID = 1;
1171        
1172        public boolean[] optionals()
1173        { return new boolean[] { false, false, false, false, false, false, false, false, false, false, false, true, true, true, true, }; }
1174        
1175        /** Document URL that <CODE>Document</CODE> or <CODE>FrameOwner</CODE> node points to. */
1176        public final int documentURL;
1177        
1178        /** Document title. */
1179        public final int title;
1180        
1181        /** Base URL that <CODE>Document</CODE> or <CODE>FrameOwner</CODE> node uses for URL completion. */
1182        public final int baseURL;
1183        
1184        /** Contains the document's content language. */
1185        public final int contentLanguage;
1186        
1187        /** Contains the document's character set encoding. */
1188        public final int encodingName;
1189        
1190        /** <CODE>DocumentType</CODE> node's publicId. */
1191        public final int publicId;
1192        
1193        /** <CODE>DocumentType</CODE> node's systemId. */
1194        public final int systemId;
1195        
1196        /** Frame ID for frame owner elements and also for the document node. */
1197        public final int frameId;
1198        
1199        /** A table with dom nodes. */
1200        public final DOMSnapshot.NodeTreeSnapshot nodes;
1201        
1202        /** The nodes in the layout tree. */
1203        public final DOMSnapshot.LayoutTreeSnapshot layout;
1204        
1205        /** The post-layout inline text nodes. */
1206        public final DOMSnapshot.TextBoxSnapshot textBoxes;
1207        
1208        /**
1209         * Horizontal scroll offset.
1210         * <BR />
1211         * <BR /><B>OPTIONAL</B>
1212         */
1213        public final Number scrollOffsetX;
1214        
1215        /**
1216         * Vertical scroll offset.
1217         * <BR />
1218         * <BR /><B>OPTIONAL</B>
1219         */
1220        public final Number scrollOffsetY;
1221        
1222        /**
1223         * Document content width.
1224         * <BR />
1225         * <BR /><B>OPTIONAL</B>
1226         */
1227        public final Number contentWidth;
1228        
1229        /**
1230         * Document content height.
1231         * <BR />
1232         * <BR /><B>OPTIONAL</B>
1233         */
1234        public final Number contentHeight;
1235        
1236        /**
1237         * Constructor
1238         *
1239         * @param documentURL Document URL that <CODE>Document</CODE> or <CODE>FrameOwner</CODE> node points to.
1240         * 
1241         * @param title Document title.
1242         * 
1243         * @param baseURL Base URL that <CODE>Document</CODE> or <CODE>FrameOwner</CODE> node uses for URL completion.
1244         * 
1245         * @param contentLanguage Contains the document's content language.
1246         * 
1247         * @param encodingName Contains the document's character set encoding.
1248         * 
1249         * @param publicId <CODE>DocumentType</CODE> node's publicId.
1250         * 
1251         * @param systemId <CODE>DocumentType</CODE> node's systemId.
1252         * 
1253         * @param frameId Frame ID for frame owner elements and also for the document node.
1254         * 
1255         * @param nodes A table with dom nodes.
1256         * 
1257         * @param layout The nodes in the layout tree.
1258         * 
1259         * @param textBoxes The post-layout inline text nodes.
1260         * 
1261         * @param scrollOffsetX Horizontal scroll offset.
1262         * <BR /><B>OPTIONAL</B>
1263         * 
1264         * @param scrollOffsetY Vertical scroll offset.
1265         * <BR /><B>OPTIONAL</B>
1266         * 
1267         * @param contentWidth Document content width.
1268         * <BR /><B>OPTIONAL</B>
1269         * 
1270         * @param contentHeight Document content height.
1271         * <BR /><B>OPTIONAL</B>
1272         */
1273        public DocumentSnapshot(
1274                int documentURL, int title, int baseURL, int contentLanguage, int encodingName, 
1275                int publicId, int systemId, int frameId, DOMSnapshot.NodeTreeSnapshot nodes, 
1276                DOMSnapshot.LayoutTreeSnapshot layout, DOMSnapshot.TextBoxSnapshot textBoxes, 
1277                Number scrollOffsetX, Number scrollOffsetY, Number contentWidth, Number contentHeight
1278            )
1279        {
1280            // Exception-Check(s) to ensure that if any parameters which are not declared as
1281            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
1282            
1283            if (nodes == null)     THROWS.throwNPE("nodes");
1284            if (layout == null)    THROWS.throwNPE("layout");
1285            if (textBoxes == null) THROWS.throwNPE("textBoxes");
1286            
1287            this.documentURL      = documentURL;
1288            this.title            = title;
1289            this.baseURL          = baseURL;
1290            this.contentLanguage  = contentLanguage;
1291            this.encodingName     = encodingName;
1292            this.publicId         = publicId;
1293            this.systemId         = systemId;
1294            this.frameId          = frameId;
1295            this.nodes            = nodes;
1296            this.layout           = layout;
1297            this.textBoxes        = textBoxes;
1298            this.scrollOffsetX    = scrollOffsetX;
1299            this.scrollOffsetY    = scrollOffsetY;
1300            this.contentWidth     = contentWidth;
1301            this.contentHeight    = contentHeight;
1302        }
1303        
1304        /**
1305         * JSON Object Constructor
1306         * @param jo A Json-Object having data about an instance of {@code 'DocumentSnapshot'}.
1307         */
1308        public DocumentSnapshot (JsonObject jo)
1309        {
1310            this.documentURL      = ReadPrimJSON.getInt(jo, "documentURL");
1311            this.title            = ReadPrimJSON.getInt(jo, "title");
1312            this.baseURL          = ReadPrimJSON.getInt(jo, "baseURL");
1313            this.contentLanguage  = ReadPrimJSON.getInt(jo, "contentLanguage");
1314            this.encodingName     = ReadPrimJSON.getInt(jo, "encodingName");
1315            this.publicId         = ReadPrimJSON.getInt(jo, "publicId");
1316            this.systemId         = ReadPrimJSON.getInt(jo, "systemId");
1317            this.frameId          = ReadPrimJSON.getInt(jo, "frameId");
1318            this.nodes            = ReadJSON.getObject(jo, "nodes", DOMSnapshot.NodeTreeSnapshot.class, false, true);
1319            this.layout           = ReadJSON.getObject(jo, "layout", DOMSnapshot.LayoutTreeSnapshot.class, false, true);
1320            this.textBoxes        = ReadJSON.getObject(jo, "textBoxes", DOMSnapshot.TextBoxSnapshot.class, false, true);
1321            this.scrollOffsetX    = ReadNumberJSON.get(jo, "scrollOffsetX", true, false);
1322            this.scrollOffsetY    = ReadNumberJSON.get(jo, "scrollOffsetY", true, false);
1323            this.contentWidth     = ReadNumberJSON.get(jo, "contentWidth", true, false);
1324            this.contentHeight    = ReadNumberJSON.get(jo, "contentHeight", true, false);
1325        }
1326        
1327        
1328        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
1329        public boolean equals(Object other)
1330        {
1331            if (this == other)                       return true;
1332            if (other == null)                       return false;
1333            if (other.getClass() != this.getClass()) return false;
1334        
1335            DocumentSnapshot o = (DocumentSnapshot) other;
1336        
1337            return
1338                    Objects.equals(this.documentURL, o.documentURL)
1339                &&  Objects.equals(this.title, o.title)
1340                &&  Objects.equals(this.baseURL, o.baseURL)
1341                &&  Objects.equals(this.contentLanguage, o.contentLanguage)
1342                &&  Objects.equals(this.encodingName, o.encodingName)
1343                &&  Objects.equals(this.publicId, o.publicId)
1344                &&  Objects.equals(this.systemId, o.systemId)
1345                &&  Objects.equals(this.frameId, o.frameId)
1346                &&  Objects.equals(this.nodes, o.nodes)
1347                &&  Objects.equals(this.layout, o.layout)
1348                &&  Objects.equals(this.textBoxes, o.textBoxes)
1349                &&  Objects.equals(this.scrollOffsetX, o.scrollOffsetX)
1350                &&  Objects.equals(this.scrollOffsetY, o.scrollOffsetY)
1351                &&  Objects.equals(this.contentWidth, o.contentWidth)
1352                &&  Objects.equals(this.contentHeight, o.contentHeight);
1353        }
1354        
1355        /** Generates a Hash-Code for {@code 'this'} instance */
1356        public int hashCode()
1357        {
1358            return
1359                    this.documentURL
1360                +   this.title
1361                +   this.baseURL
1362                +   this.contentLanguage
1363                +   this.encodingName
1364                +   this.publicId
1365                +   this.systemId
1366                +   this.frameId
1367                +   this.nodes.hashCode()
1368                +   this.layout.hashCode()
1369                +   this.textBoxes.hashCode()
1370                +   Objects.hashCode(this.scrollOffsetX)
1371                +   Objects.hashCode(this.scrollOffsetY)
1372                +   Objects.hashCode(this.contentWidth)
1373                +   Objects.hashCode(this.contentHeight);
1374        }
1375    }
1376    
1377    /** Table containing nodes. */
1378    public static class NodeTreeSnapshot
1379        extends BaseType
1380        implements java.io.Serializable
1381    {
1382        /** For Object Serialization.  java.io.Serializable */
1383        protected static final long serialVersionUID = 1;
1384        
1385        public boolean[] optionals()
1386        { return new boolean[] { true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, }; }
1387        
1388        /**
1389         * Parent node index.
1390         * <BR />
1391         * <BR /><B>OPTIONAL</B>
1392         */
1393        public final int[] parentIndex;
1394        
1395        /**
1396         * <CODE>Node</CODE>'s nodeType.
1397         * <BR />
1398         * <BR /><B>OPTIONAL</B>
1399         */
1400        public final int[] nodeType;
1401        
1402        /**
1403         * Type of the shadow root the <CODE>Node</CODE> is in. String values are equal to the <CODE>ShadowRootType</CODE> enum.
1404         * <BR />
1405         * <BR /><B>OPTIONAL</B>
1406         */
1407        public final DOMSnapshot.RareStringData shadowRootType;
1408        
1409        /**
1410         * <CODE>Node</CODE>'s nodeName.
1411         * <BR />
1412         * <BR /><B>OPTIONAL</B>
1413         */
1414        public final int[] nodeName;
1415        
1416        /**
1417         * <CODE>Node</CODE>'s nodeValue.
1418         * <BR />
1419         * <BR /><B>OPTIONAL</B>
1420         */
1421        public final int[] nodeValue;
1422        
1423        /**
1424         * <CODE>Node</CODE>'s id, corresponds to DOM.Node.backendNodeId.
1425         * <BR />
1426         * <BR /><B>OPTIONAL</B>
1427         */
1428        public final int[] backendNodeId;
1429        
1430        /**
1431         * Attributes of an <CODE>Element</CODE> node. Flatten name, value pairs.
1432         * <BR />
1433         * <BR /><B>OPTIONAL</B>
1434         */
1435        public final int[][] attributes;
1436        
1437        /**
1438         * Only set for textarea elements, contains the text value.
1439         * <BR />
1440         * <BR /><B>OPTIONAL</B>
1441         */
1442        public final DOMSnapshot.RareStringData textValue;
1443        
1444        /**
1445         * Only set for input elements, contains the input's associated text value.
1446         * <BR />
1447         * <BR /><B>OPTIONAL</B>
1448         */
1449        public final DOMSnapshot.RareStringData inputValue;
1450        
1451        /**
1452         * Only set for radio and checkbox input elements, indicates if the element has been checked
1453         * <BR />
1454         * <BR /><B>OPTIONAL</B>
1455         */
1456        public final DOMSnapshot.RareBooleanData inputChecked;
1457        
1458        /**
1459         * Only set for option elements, indicates if the element has been selected
1460         * <BR />
1461         * <BR /><B>OPTIONAL</B>
1462         */
1463        public final DOMSnapshot.RareBooleanData optionSelected;
1464        
1465        /**
1466         * The index of the document in the list of the snapshot documents.
1467         * <BR />
1468         * <BR /><B>OPTIONAL</B>
1469         */
1470        public final DOMSnapshot.RareIntegerData contentDocumentIndex;
1471        
1472        /**
1473         * Type of a pseudo element node.
1474         * <BR />
1475         * <BR /><B>OPTIONAL</B>
1476         */
1477        public final DOMSnapshot.RareStringData pseudoType;
1478        
1479        /**
1480         * Whether this DOM node responds to mouse clicks. This includes nodes that have had click
1481         * event listeners attached via JavaScript as well as anchor tags that naturally navigate when
1482         * clicked.
1483         * <BR />
1484         * <BR /><B>OPTIONAL</B>
1485         */
1486        public final DOMSnapshot.RareBooleanData isClickable;
1487        
1488        /**
1489         * The selected url for nodes with a srcset attribute.
1490         * <BR />
1491         * <BR /><B>OPTIONAL</B>
1492         */
1493        public final DOMSnapshot.RareStringData currentSourceURL;
1494        
1495        /**
1496         * The url of the script (if any) that generates this node.
1497         * <BR />
1498         * <BR /><B>OPTIONAL</B>
1499         */
1500        public final DOMSnapshot.RareStringData originURL;
1501        
1502        /**
1503         * Constructor
1504         *
1505         * @param parentIndex Parent node index.
1506         * <BR /><B>OPTIONAL</B>
1507         * 
1508         * @param nodeType <CODE>Node</CODE>'s nodeType.
1509         * <BR /><B>OPTIONAL</B>
1510         * 
1511         * @param shadowRootType Type of the shadow root the <CODE>Node</CODE> is in. String values are equal to the <CODE>ShadowRootType</CODE> enum.
1512         * <BR /><B>OPTIONAL</B>
1513         * 
1514         * @param nodeName <CODE>Node</CODE>'s nodeName.
1515         * <BR /><B>OPTIONAL</B>
1516         * 
1517         * @param nodeValue <CODE>Node</CODE>'s nodeValue.
1518         * <BR /><B>OPTIONAL</B>
1519         * 
1520         * @param backendNodeId <CODE>Node</CODE>'s id, corresponds to DOM.Node.backendNodeId.
1521         * <BR /><B>OPTIONAL</B>
1522         * 
1523         * @param attributes Attributes of an <CODE>Element</CODE> node. Flatten name, value pairs.
1524         * <BR /><B>OPTIONAL</B>
1525         * 
1526         * @param textValue Only set for textarea elements, contains the text value.
1527         * <BR /><B>OPTIONAL</B>
1528         * 
1529         * @param inputValue Only set for input elements, contains the input's associated text value.
1530         * <BR /><B>OPTIONAL</B>
1531         * 
1532         * @param inputChecked Only set for radio and checkbox input elements, indicates if the element has been checked
1533         * <BR /><B>OPTIONAL</B>
1534         * 
1535         * @param optionSelected Only set for option elements, indicates if the element has been selected
1536         * <BR /><B>OPTIONAL</B>
1537         * 
1538         * @param contentDocumentIndex The index of the document in the list of the snapshot documents.
1539         * <BR /><B>OPTIONAL</B>
1540         * 
1541         * @param pseudoType Type of a pseudo element node.
1542         * <BR /><B>OPTIONAL</B>
1543         * 
1544         * @param isClickable 
1545         * Whether this DOM node responds to mouse clicks. This includes nodes that have had click
1546         * event listeners attached via JavaScript as well as anchor tags that naturally navigate when
1547         * clicked.
1548         * <BR /><B>OPTIONAL</B>
1549         * 
1550         * @param currentSourceURL The selected url for nodes with a srcset attribute.
1551         * <BR /><B>OPTIONAL</B>
1552         * 
1553         * @param originURL The url of the script (if any) that generates this node.
1554         * <BR /><B>OPTIONAL</B>
1555         */
1556        public NodeTreeSnapshot(
1557                int[] parentIndex, int[] nodeType, DOMSnapshot.RareStringData shadowRootType, 
1558                int[] nodeName, int[] nodeValue, int[] backendNodeId, int[][] attributes, 
1559                DOMSnapshot.RareStringData textValue, DOMSnapshot.RareStringData inputValue, 
1560                DOMSnapshot.RareBooleanData inputChecked, 
1561                DOMSnapshot.RareBooleanData optionSelected, 
1562                DOMSnapshot.RareIntegerData contentDocumentIndex, 
1563                DOMSnapshot.RareStringData pseudoType, DOMSnapshot.RareBooleanData isClickable, 
1564                DOMSnapshot.RareStringData currentSourceURL, DOMSnapshot.RareStringData originURL
1565            )
1566        {
1567            this.parentIndex           = parentIndex;
1568            this.nodeType              = nodeType;
1569            this.shadowRootType        = shadowRootType;
1570            this.nodeName              = nodeName;
1571            this.nodeValue             = nodeValue;
1572            this.backendNodeId         = backendNodeId;
1573            this.attributes            = attributes;
1574            this.textValue             = textValue;
1575            this.inputValue            = inputValue;
1576            this.inputChecked          = inputChecked;
1577            this.optionSelected        = optionSelected;
1578            this.contentDocumentIndex  = contentDocumentIndex;
1579            this.pseudoType            = pseudoType;
1580            this.isClickable           = isClickable;
1581            this.currentSourceURL      = currentSourceURL;
1582            this.originURL             = originURL;
1583        }
1584        
1585        /**
1586         * JSON Object Constructor
1587         * @param jo A Json-Object having data about an instance of {@code 'NodeTreeSnapshot'}.
1588         */
1589        public NodeTreeSnapshot (JsonObject jo)
1590        {
1591            this.parentIndex = (jo.getJsonArray("parentIndex") == null)
1592                ? null
1593                : RJArrIntoPrimArray.intArr(jo.getJsonArray("parentIndex"), -1, 0, null);
1594        
1595            this.nodeType = (jo.getJsonArray("nodeType") == null)
1596                ? null
1597                : RJArrIntoPrimArray.intArr(jo.getJsonArray("nodeType"), -1, 0, null);
1598        
1599            this.shadowRootType        = ReadJSON.getObject(jo, "shadowRootType", DOMSnapshot.RareStringData.class, true, false);
1600            this.nodeName = (jo.getJsonArray("nodeName") == null)
1601                ? null
1602                : RJArrIntoPrimArray.intArr(jo.getJsonArray("nodeName"), -1, 0, null);
1603        
1604            this.nodeValue = (jo.getJsonArray("nodeValue") == null)
1605                ? null
1606                : RJArrIntoPrimArray.intArr(jo.getJsonArray("nodeValue"), -1, 0, null);
1607        
1608            this.backendNodeId = (jo.getJsonArray("backendNodeId") == null)
1609                ? null
1610                : RJArrIntoPrimArray.intArr(jo.getJsonArray("backendNodeId"), -1, 0, null);
1611        
1612            this.attributes = (jo.getJsonArray("attributes") == null)
1613                ? null
1614                : RJArrDimN.intArr(jo.getJsonArray("attributes"), -1, 0, null, int[][].class);
1615        
1616            this.textValue             = ReadJSON.getObject(jo, "textValue", DOMSnapshot.RareStringData.class, true, false);
1617            this.inputValue            = ReadJSON.getObject(jo, "inputValue", DOMSnapshot.RareStringData.class, true, false);
1618            this.inputChecked          = ReadJSON.getObject(jo, "inputChecked", DOMSnapshot.RareBooleanData.class, true, false);
1619            this.optionSelected        = ReadJSON.getObject(jo, "optionSelected", DOMSnapshot.RareBooleanData.class, true, false);
1620            this.contentDocumentIndex  = ReadJSON.getObject(jo, "contentDocumentIndex", DOMSnapshot.RareIntegerData.class, true, false);
1621            this.pseudoType            = ReadJSON.getObject(jo, "pseudoType", DOMSnapshot.RareStringData.class, true, false);
1622            this.isClickable           = ReadJSON.getObject(jo, "isClickable", DOMSnapshot.RareBooleanData.class, true, false);
1623            this.currentSourceURL      = ReadJSON.getObject(jo, "currentSourceURL", DOMSnapshot.RareStringData.class, true, false);
1624            this.originURL             = ReadJSON.getObject(jo, "originURL", DOMSnapshot.RareStringData.class, true, false);
1625        }
1626        
1627        
1628        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
1629        public boolean equals(Object other)
1630        {
1631            if (this == other)                       return true;
1632            if (other == null)                       return false;
1633            if (other.getClass() != this.getClass()) return false;
1634        
1635            NodeTreeSnapshot o = (NodeTreeSnapshot) other;
1636        
1637            return
1638                    Arrays.equals(this.parentIndex, o.parentIndex)
1639                &&  Arrays.equals(this.nodeType, o.nodeType)
1640                &&  Objects.equals(this.shadowRootType, o.shadowRootType)
1641                &&  Arrays.equals(this.nodeName, o.nodeName)
1642                &&  Arrays.equals(this.nodeValue, o.nodeValue)
1643                &&  Arrays.equals(this.backendNodeId, o.backendNodeId)
1644                &&  Arrays.equals(this.attributes, o.attributes)
1645                &&  Objects.equals(this.textValue, o.textValue)
1646                &&  Objects.equals(this.inputValue, o.inputValue)
1647                &&  Objects.equals(this.inputChecked, o.inputChecked)
1648                &&  Objects.equals(this.optionSelected, o.optionSelected)
1649                &&  Objects.equals(this.contentDocumentIndex, o.contentDocumentIndex)
1650                &&  Objects.equals(this.pseudoType, o.pseudoType)
1651                &&  Objects.equals(this.isClickable, o.isClickable)
1652                &&  Objects.equals(this.currentSourceURL, o.currentSourceURL)
1653                &&  Objects.equals(this.originURL, o.originURL);
1654        }
1655        
1656        /** Generates a Hash-Code for {@code 'this'} instance */
1657        public int hashCode()
1658        {
1659            return
1660                    Arrays.hashCode(this.parentIndex)
1661                +   Arrays.hashCode(this.nodeType)
1662                +   this.shadowRootType.hashCode()
1663                +   Arrays.hashCode(this.nodeName)
1664                +   Arrays.hashCode(this.nodeValue)
1665                +   Arrays.hashCode(this.backendNodeId)
1666                +   Arrays.hashCode(this.attributes)
1667                +   this.textValue.hashCode()
1668                +   this.inputValue.hashCode()
1669                +   this.inputChecked.hashCode()
1670                +   this.optionSelected.hashCode()
1671                +   this.contentDocumentIndex.hashCode()
1672                +   this.pseudoType.hashCode()
1673                +   this.isClickable.hashCode()
1674                +   this.currentSourceURL.hashCode()
1675                +   this.originURL.hashCode();
1676        }
1677    }
1678    
1679    /** Table of details of an element in the DOM tree with a LayoutObject. */
1680    public static class LayoutTreeSnapshot
1681        extends BaseType
1682        implements java.io.Serializable
1683    {
1684        /** For Object Serialization.  java.io.Serializable */
1685        protected static final long serialVersionUID = 1;
1686        
1687        public boolean[] optionals()
1688        { return new boolean[] { false, false, false, false, false, true, true, true, true, true, true, }; }
1689        
1690        /** Index of the corresponding node in the <CODE>NodeTreeSnapshot</CODE> array returned by <CODE>captureSnapshot</CODE>. */
1691        public final int[] nodeIndex;
1692        
1693        /** Array of indexes specifying computed style strings, filtered according to the <CODE>computedStyles</CODE> parameter passed to <CODE>captureSnapshot</CODE>. */
1694        public final int[][] styles;
1695        
1696        /** The absolute position bounding box. */
1697        public final Number[][] bounds;
1698        
1699        /** Contents of the LayoutText, if any. */
1700        public final int[] text;
1701        
1702        /** Stacking context information. */
1703        public final DOMSnapshot.RareBooleanData stackingContexts;
1704        
1705        /**
1706         * Global paint order index, which is determined by the stacking order of the nodes. Nodes
1707         * that are painted together will have the same index. Only provided if includePaintOrder in
1708         * captureSnapshot was true.
1709         * <BR />
1710         * <BR /><B>OPTIONAL</B>
1711         */
1712        public final int[] paintOrders;
1713        
1714        /**
1715         * The offset rect of nodes. Only available when includeDOMRects is set to true
1716         * <BR />
1717         * <BR /><B>OPTIONAL</B>
1718         */
1719        public final Number[][] offsetRects;
1720        
1721        /**
1722         * The scroll rect of nodes. Only available when includeDOMRects is set to true
1723         * <BR />
1724         * <BR /><B>OPTIONAL</B>
1725         */
1726        public final Number[][] scrollRects;
1727        
1728        /**
1729         * The client rect of nodes. Only available when includeDOMRects is set to true
1730         * <BR />
1731         * <BR /><B>OPTIONAL</B>
1732         */
1733        public final Number[][] clientRects;
1734        
1735        /**
1736         * The list of background colors that are blended with colors of overlapping elements.
1737         * <BR />
1738         * <BR /><B>OPTIONAL</B>
1739         * <BR /><B>EXPERIMENTAL</B>
1740         */
1741        public final int[] blendedBackgroundColors;
1742        
1743        /**
1744         * The list of computed text opacities.
1745         * <BR />
1746         * <BR /><B>OPTIONAL</B>
1747         * <BR /><B>EXPERIMENTAL</B>
1748         */
1749        public final Number[] textColorOpacities;
1750        
1751        /**
1752         * Constructor
1753         *
1754         * @param nodeIndex Index of the corresponding node in the <CODE>NodeTreeSnapshot</CODE> array returned by <CODE>captureSnapshot</CODE>.
1755         * 
1756         * @param styles Array of indexes specifying computed style strings, filtered according to the <CODE>computedStyles</CODE> parameter passed to <CODE>captureSnapshot</CODE>.
1757         * 
1758         * @param bounds The absolute position bounding box.
1759         * 
1760         * @param text Contents of the LayoutText, if any.
1761         * 
1762         * @param stackingContexts Stacking context information.
1763         * 
1764         * @param paintOrders 
1765         * Global paint order index, which is determined by the stacking order of the nodes. Nodes
1766         * that are painted together will have the same index. Only provided if includePaintOrder in
1767         * captureSnapshot was true.
1768         * <BR /><B>OPTIONAL</B>
1769         * 
1770         * @param offsetRects The offset rect of nodes. Only available when includeDOMRects is set to true
1771         * <BR /><B>OPTIONAL</B>
1772         * 
1773         * @param scrollRects The scroll rect of nodes. Only available when includeDOMRects is set to true
1774         * <BR /><B>OPTIONAL</B>
1775         * 
1776         * @param clientRects The client rect of nodes. Only available when includeDOMRects is set to true
1777         * <BR /><B>OPTIONAL</B>
1778         * 
1779         * @param blendedBackgroundColors The list of background colors that are blended with colors of overlapping elements.
1780         * <BR /><B>OPTIONAL</B>
1781         * <BR /><B>EXPERIMENTAL</B>
1782         * 
1783         * @param textColorOpacities The list of computed text opacities.
1784         * <BR /><B>OPTIONAL</B>
1785         * <BR /><B>EXPERIMENTAL</B>
1786         */
1787        public LayoutTreeSnapshot(
1788                int[] nodeIndex, int[][] styles, Number[][] bounds, int[] text, 
1789                DOMSnapshot.RareBooleanData stackingContexts, int[] paintOrders, 
1790                Number[][] offsetRects, Number[][] scrollRects, Number[][] clientRects, 
1791                int[] blendedBackgroundColors, Number[] textColorOpacities
1792            )
1793        {
1794            // Exception-Check(s) to ensure that if any parameters which are not declared as
1795            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
1796            
1797            if (nodeIndex == null)        THROWS.throwNPE("nodeIndex");
1798            if (styles == null)           THROWS.throwNPE("styles");
1799            if (bounds == null)           THROWS.throwNPE("bounds");
1800            if (text == null)             THROWS.throwNPE("text");
1801            if (stackingContexts == null) THROWS.throwNPE("stackingContexts");
1802            
1803            this.nodeIndex                = nodeIndex;
1804            this.styles                   = styles;
1805            this.bounds                   = bounds;
1806            this.text                     = text;
1807            this.stackingContexts         = stackingContexts;
1808            this.paintOrders              = paintOrders;
1809            this.offsetRects              = offsetRects;
1810            this.scrollRects              = scrollRects;
1811            this.clientRects              = clientRects;
1812            this.blendedBackgroundColors  = blendedBackgroundColors;
1813            this.textColorOpacities       = textColorOpacities;
1814        }
1815        
1816        /**
1817         * JSON Object Constructor
1818         * @param jo A Json-Object having data about an instance of {@code 'LayoutTreeSnapshot'}.
1819         */
1820        public LayoutTreeSnapshot (JsonObject jo)
1821        {
1822            this.nodeIndex = (jo.getJsonArray("nodeIndex") == null)
1823                ? null
1824                : RJArrIntoPrimArray.intArr(jo.getJsonArray("nodeIndex"), -1, 0, null);
1825        
1826            this.styles = (jo.getJsonArray("styles") == null)
1827                ? null
1828                : RJArrDimN.intArr(jo.getJsonArray("styles"), -1, 0, null, int[][].class);
1829        
1830            this.bounds = (jo.getJsonArray("bounds") == null)
1831                ? null
1832                : RJArrDimN.arrNumber(jo.getJsonArray("bounds"), -1, 0, null, Number[][].class);
1833        
1834            this.text = (jo.getJsonArray("text") == null)
1835                ? null
1836                : RJArrIntoPrimArray.intArr(jo.getJsonArray("text"), -1, 0, null);
1837        
1838            this.stackingContexts         = ReadJSON.getObject(jo, "stackingContexts", DOMSnapshot.RareBooleanData.class, false, true);
1839            this.paintOrders = (jo.getJsonArray("paintOrders") == null)
1840                ? null
1841                : RJArrIntoPrimArray.intArr(jo.getJsonArray("paintOrders"), -1, 0, null);
1842        
1843            this.offsetRects = (jo.getJsonArray("offsetRects") == null)
1844                ? null
1845                : RJArrDimN.arrNumber(jo.getJsonArray("offsetRects"), -1, 0, null, Number[][].class);
1846        
1847            this.scrollRects = (jo.getJsonArray("scrollRects") == null)
1848                ? null
1849                : RJArrDimN.arrNumber(jo.getJsonArray("scrollRects"), -1, 0, null, Number[][].class);
1850        
1851            this.clientRects = (jo.getJsonArray("clientRects") == null)
1852                ? null
1853                : RJArrDimN.arrNumber(jo.getJsonArray("clientRects"), -1, 0, null, Number[][].class);
1854        
1855            this.blendedBackgroundColors = (jo.getJsonArray("blendedBackgroundColors") == null)
1856                ? null
1857                : RJArrIntoPrimArray.intArr(jo.getJsonArray("blendedBackgroundColors"), -1, 0, null);
1858        
1859            this.textColorOpacities = (jo.getJsonArray("textColorOpacities") == null)
1860                ? null
1861                : RJArrIntoBoxedStream.numberArr(jo.getJsonArray("textColorOpacities"), -1, 0, null).toArray(Number[]::new);
1862        
1863        }
1864        
1865        
1866        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
1867        public boolean equals(Object other)
1868        {
1869            if (this == other)                       return true;
1870            if (other == null)                       return false;
1871            if (other.getClass() != this.getClass()) return false;
1872        
1873            LayoutTreeSnapshot o = (LayoutTreeSnapshot) other;
1874        
1875            return
1876                    Arrays.equals(this.nodeIndex, o.nodeIndex)
1877                &&  Arrays.equals(this.styles, o.styles)
1878                &&  Arrays.deepEquals(this.bounds, o.bounds)
1879                &&  Arrays.equals(this.text, o.text)
1880                &&  Objects.equals(this.stackingContexts, o.stackingContexts)
1881                &&  Arrays.equals(this.paintOrders, o.paintOrders)
1882                &&  Arrays.deepEquals(this.offsetRects, o.offsetRects)
1883                &&  Arrays.deepEquals(this.scrollRects, o.scrollRects)
1884                &&  Arrays.deepEquals(this.clientRects, o.clientRects)
1885                &&  Arrays.equals(this.blendedBackgroundColors, o.blendedBackgroundColors)
1886                &&  Arrays.deepEquals(this.textColorOpacities, o.textColorOpacities);
1887        }
1888        
1889        /** Generates a Hash-Code for {@code 'this'} instance */
1890        public int hashCode()
1891        {
1892            return
1893                    Arrays.hashCode(this.nodeIndex)
1894                +   Arrays.hashCode(this.styles)
1895                +   Arrays.deepHashCode(this.bounds)
1896                +   Arrays.hashCode(this.text)
1897                +   this.stackingContexts.hashCode()
1898                +   Arrays.hashCode(this.paintOrders)
1899                +   Arrays.deepHashCode(this.offsetRects)
1900                +   Arrays.deepHashCode(this.scrollRects)
1901                +   Arrays.deepHashCode(this.clientRects)
1902                +   Arrays.hashCode(this.blendedBackgroundColors)
1903                +   Arrays.deepHashCode(this.textColorOpacities);
1904        }
1905    }
1906    
1907    /**
1908     * Table of details of the post layout rendered text positions. The exact layout should not be regarded as
1909     * stable and may change between versions.
1910     */
1911    public static class TextBoxSnapshot
1912        extends BaseType
1913        implements java.io.Serializable
1914    {
1915        /** For Object Serialization.  java.io.Serializable */
1916        protected static final long serialVersionUID = 1;
1917        
1918        public boolean[] optionals()
1919        { return new boolean[] { false, false, false, false, }; }
1920        
1921        /** Index of the layout tree node that owns this box collection. */
1922        public final int[] layoutIndex;
1923        
1924        /** The absolute position bounding box. */
1925        public final Number[][] bounds;
1926        
1927        /**
1928         * The starting index in characters, for this post layout textbox substring. Characters that
1929         * would be represented as a surrogate pair in UTF-16 have length 2.
1930         */
1931        public final int[] start;
1932        
1933        /**
1934         * The number of characters in this post layout textbox substring. Characters that would be
1935         * represented as a surrogate pair in UTF-16 have length 2.
1936         */
1937        public final int[] length;
1938        
1939        /**
1940         * Constructor
1941         *
1942         * @param layoutIndex Index of the layout tree node that owns this box collection.
1943         * 
1944         * @param bounds The absolute position bounding box.
1945         * 
1946         * @param start 
1947         * The starting index in characters, for this post layout textbox substring. Characters that
1948         * would be represented as a surrogate pair in UTF-16 have length 2.
1949         * 
1950         * @param length 
1951         * The number of characters in this post layout textbox substring. Characters that would be
1952         * represented as a surrogate pair in UTF-16 have length 2.
1953         */
1954        public TextBoxSnapshot(int[] layoutIndex, Number[][] bounds, int[] start, int[] length)
1955        {
1956            // Exception-Check(s) to ensure that if any parameters which are not declared as
1957            // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
1958            
1959            if (layoutIndex == null) THROWS.throwNPE("layoutIndex");
1960            if (bounds == null)      THROWS.throwNPE("bounds");
1961            if (start == null)       THROWS.throwNPE("start");
1962            if (length == null)      THROWS.throwNPE("length");
1963            
1964            this.layoutIndex  = layoutIndex;
1965            this.bounds       = bounds;
1966            this.start        = start;
1967            this.length       = length;
1968        }
1969        
1970        /**
1971         * JSON Object Constructor
1972         * @param jo A Json-Object having data about an instance of {@code 'TextBoxSnapshot'}.
1973         */
1974        public TextBoxSnapshot (JsonObject jo)
1975        {
1976            this.layoutIndex = (jo.getJsonArray("layoutIndex") == null)
1977                ? null
1978                : RJArrIntoPrimArray.intArr(jo.getJsonArray("layoutIndex"), -1, 0, null);
1979        
1980            this.bounds = (jo.getJsonArray("bounds") == null)
1981                ? null
1982                : RJArrDimN.arrNumber(jo.getJsonArray("bounds"), -1, 0, null, Number[][].class);
1983        
1984            this.start = (jo.getJsonArray("start") == null)
1985                ? null
1986                : RJArrIntoPrimArray.intArr(jo.getJsonArray("start"), -1, 0, null);
1987        
1988            this.length = (jo.getJsonArray("length") == null)
1989                ? null
1990                : RJArrIntoPrimArray.intArr(jo.getJsonArray("length"), -1, 0, null);
1991        
1992        }
1993        
1994        
1995        /** Checks whether {@code 'this'} equals an input Java-{@code Object} */
1996        public boolean equals(Object other)
1997        {
1998            if (this == other)                       return true;
1999            if (other == null)                       return false;
2000            if (other.getClass() != this.getClass()) return false;
2001        
2002            TextBoxSnapshot o = (TextBoxSnapshot) other;
2003        
2004            return
2005                    Arrays.equals(this.layoutIndex, o.layoutIndex)
2006                &&  Arrays.deepEquals(this.bounds, o.bounds)
2007                &&  Arrays.equals(this.start, o.start)
2008                &&  Arrays.equals(this.length, o.length);
2009        }
2010        
2011        /** Generates a Hash-Code for {@code 'this'} instance */
2012        public int hashCode()
2013        {
2014            return
2015                    Arrays.hashCode(this.layoutIndex)
2016                +   Arrays.deepHashCode(this.bounds)
2017                +   Arrays.hashCode(this.start)
2018                +   Arrays.hashCode(this.length);
2019        }
2020    }
2021    
2022    
2023    // Counter for keeping the WebSocket Request ID's distinct.
2024    private static int counter = 1;
2025    
2026    /**
2027     * Disables DOM snapshot agent for the given page.
2028     * 
2029     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
2030     * {@link Ret0}&gt;</CODE>
2031     *
2032     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
2033     * browser receives the invocation-request.
2034     *
2035     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
2036     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
2037     * {@code >} to ensure the Browser Function has run to completion.
2038     */
2039    public static Script<String, JsonObject, Ret0> disable()
2040    {
2041        final int          webSocketID = 17000000 + counter++;
2042        final boolean[]    optionals   = new boolean[0];
2043        
2044        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
2045        String requestJSON = WriteJSON.get(
2046            parameterTypes.get("disable"),
2047            parameterNames.get("disable"),
2048            optionals, webSocketID,
2049            "DOMSnapshot.disable"
2050        );
2051        
2052        // This Remote Command does not have a Return-Value.
2053        return new Script<>
2054            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
2055    }
2056    
2057    /**
2058     * Enables DOM snapshot agent for the given page.
2059     * 
2060     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
2061     * {@link Ret0}&gt;</CODE>
2062     *
2063     * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the
2064     * browser receives the invocation-request.
2065     *
2066     * <BR /><BR />This Browser-Function <I>does not have</I> a return-value.  You may choose to
2067     * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0}
2068     * {@code >} to ensure the Browser Function has run to completion.
2069     */
2070    public static Script<String, JsonObject, Ret0> enable()
2071    {
2072        final int          webSocketID = 17001000 + counter++;
2073        final boolean[]    optionals   = new boolean[0];
2074        
2075        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
2076        String requestJSON = WriteJSON.get(
2077            parameterTypes.get("enable"),
2078            parameterNames.get("enable"),
2079            optionals, webSocketID,
2080            "DOMSnapshot.enable"
2081        );
2082        
2083        // This Remote Command does not have a Return-Value.
2084        return new Script<>
2085            (webSocketID, requestJSON, VOID_RETURN.NoReturnValues);
2086    }
2087    
2088    /**
2089     * Returns a document snapshot, including the full DOM tree of the root node (including iframes,
2090     * template contents, and imported documents) in a flattened array, as well as layout and
2091     * white-listed computed style information for the nodes. Shadow DOM in the returned DOM tree is
2092     * flattened.
2093     * <BR /><B>DEPRECATED</B>
2094     * 
2095     * @param computedStyleWhitelist Whitelist of computed styles to return.
2096     * 
2097     * @param includeEventListeners Whether or not to retrieve details of DOM listeners (default false).
2098     * <BR /><B>OPTIONAL</B>
2099     * 
2100     * @param includePaintOrder Whether to determine and include the paint order index of LayoutTreeNodes (default false).
2101     * <BR /><B>OPTIONAL</B>
2102     * 
2103     * @param includeUserAgentShadowTree Whether to include UA shadow tree in the snapshot (default false).
2104     * <BR /><B>OPTIONAL</B>
2105     * 
2106     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
2107     * {@link Ret3}&gt;</CODE>
2108     *
2109     * <BR /><BR />This {@link Script} may be <B STYLE='color:red'>executed</B> (using 
2110     * {@link Script#exec()}), and a {@link Promise} returned.
2111     *
2112     * <BR /><BR />When the {@code Promise} is <B STYLE='color: red'>awaited</B>
2113     * (using {@link Promise#await()}), the {@code Ret3} will subsequently
2114     * be returned from that call.
2115     * 
2116     * <BR /><BR />The <B STYLE='color: red'>returned</B> values are encapsulated
2117     * in an instance of <B>{@link Ret3}</B>
2118     *
2119     * <BR /><BR /><UL CLASS=JDUL>
2120     * <LI><CODE><B>Ret3.a:</B> {@link DOMSnapshot.DOMNode}[] (<B>domNodes</B>)</CODE>
2121     *     <BR />The nodes in the DOM tree. The DOMNode at index 0 corresponds to the root document.
2122     *     <BR /><BR /></LI>
2123     * <LI><CODE><B>Ret3.b:</B> {@link DOMSnapshot.LayoutTreeNode}[] (<B>layoutTreeNodes</B>)</CODE>
2124     *     <BR />The nodes in the layout tree.
2125     *     <BR /><BR /></LI>
2126     * <LI><CODE><B>Ret3.c:</B> {@link DOMSnapshot.ComputedStyle}[] (<B>computedStyles</B>)</CODE>
2127     *     <BR />Whitelisted ComputedStyle properties for each node in the layout tree.
2128     *     </LI>
2129     * </UL>
2130     */
2131    public static Script<String, JsonObject, Ret3<DOMSnapshot.DOMNode[], DOMSnapshot.LayoutTreeNode[], DOMSnapshot.ComputedStyle[]>> 
2132        getSnapshot(
2133            String[] computedStyleWhitelist, Boolean includeEventListeners, 
2134            Boolean includePaintOrder, Boolean includeUserAgentShadowTree
2135        )
2136    {
2137        // Exception-Check(s) to ensure that if any parameters which are not declared as
2138        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
2139        
2140        if (computedStyleWhitelist == null) THROWS.throwNPE("computedStyleWhitelist");
2141        
2142        final int       webSocketID = 17002000 + counter++;
2143        final boolean[] optionals   = { false, true, true, true, };
2144        
2145        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
2146        String requestJSON = WriteJSON.get(
2147            parameterTypes.get("getSnapshot"),
2148            parameterNames.get("getSnapshot"),
2149            optionals, webSocketID,
2150            "DOMSnapshot.getSnapshot",
2151            computedStyleWhitelist, includeEventListeners, includePaintOrder,
2152            includeUserAgentShadowTree
2153        );
2154        
2155        // 'JSON Binding' ... Converts Browser Response-JSON into Java-Type 'Ret3'
2156        Function<JsonObject, Ret3<DOMSnapshot.DOMNode[], DOMSnapshot.LayoutTreeNode[], DOMSnapshot.ComputedStyle[]>> 
2157            responseProcessor = (JsonObject jo) -> new Ret3<>(
2158                (jo.getJsonArray("domNodes") == null)
2159                    ? null
2160                    : RJArrIntoStream.objArr(jo.getJsonArray("domNodes"), null, 0, DOMSnapshot.DOMNode.class).toArray(DOMSnapshot.DOMNode[]::new),
2161                (jo.getJsonArray("layoutTreeNodes") == null)
2162                    ? null
2163                    : RJArrIntoStream.objArr(jo.getJsonArray("layoutTreeNodes"), null, 0, DOMSnapshot.LayoutTreeNode.class).toArray(DOMSnapshot.LayoutTreeNode[]::new),
2164                (jo.getJsonArray("computedStyles") == null)
2165                    ? null
2166                    : RJArrIntoStream.objArr(jo.getJsonArray("computedStyles"), null, 0, DOMSnapshot.ComputedStyle.class).toArray(DOMSnapshot.ComputedStyle[]::new)
2167            );
2168        
2169        return new Script<>(webSocketID, requestJSON, responseProcessor);
2170    }
2171    
2172    /**
2173     * Returns a document snapshot, including the full DOM tree of the root node (including iframes,
2174     * template contents, and imported documents) in a flattened array, as well as layout and
2175     * white-listed computed style information for the nodes. Shadow DOM in the returned DOM tree is
2176     * flattened.
2177     * 
2178     * @param computedStyles Whitelist of computed styles to return.
2179     * 
2180     * @param includePaintOrder Whether to include layout object paint orders into the snapshot.
2181     * <BR /><B>OPTIONAL</B>
2182     * 
2183     * @param includeDOMRects Whether to include DOM rectangles (offsetRects, clientRects, scrollRects) into the snapshot
2184     * <BR /><B>OPTIONAL</B>
2185     * 
2186     * @param includeBlendedBackgroundColors 
2187     * Whether to include blended background colors in the snapshot (default: false).
2188     * Blended background color is achieved by blending background colors of all elements
2189     * that overlap with the current element.
2190     * <BR /><B>OPTIONAL</B>
2191     * <BR /><B>EXPERIMENTAL</B>
2192     * 
2193     * @param includeTextColorOpacities 
2194     * Whether to include text color opacity in the snapshot (default: false).
2195     * An element might have the opacity property set that affects the text color of the element.
2196     * The final text color opacity is computed based on the opacity of all overlapping elements.
2197     * <BR /><B>OPTIONAL</B>
2198     * <BR /><B>EXPERIMENTAL</B>
2199     * 
2200     * @return An instance of <CODE>{@link Script}&lt;String, {@link JsonObject},
2201     * {@link Ret2}&gt;</CODE>
2202     *
2203     * <BR /><BR />This {@link Script} may be <B STYLE='color:red'>executed</B> (using 
2204     * {@link Script#exec()}), and a {@link Promise} returned.
2205     *
2206     * <BR /><BR />When the {@code Promise} is <B STYLE='color: red'>awaited</B>
2207     * (using {@link Promise#await()}), the {@code Ret2} will subsequently
2208     * be returned from that call.
2209     * 
2210     * <BR /><BR />The <B STYLE='color: red'>returned</B> values are encapsulated
2211     * in an instance of <B>{@link Ret2}</B>
2212     *
2213     * <BR /><BR /><UL CLASS=JDUL>
2214     * <LI><CODE><B>Ret2.a:</B> {@link DOMSnapshot.DocumentSnapshot}[] (<B>documents</B>)</CODE>
2215     *     <BR />The nodes in the DOM tree. The DOMNode at index 0 corresponds to the root document.
2216     *     <BR /><BR /></LI>
2217     * <LI><CODE><B>Ret2.b:</B> String[] (<B>strings</B>)</CODE>
2218     *     <BR />Shared string table that all string properties refer to with indexes.
2219     *     </LI>
2220     * </UL>
2221     */
2222    public static Script<String, JsonObject, Ret2<DOMSnapshot.DocumentSnapshot[], String[]>> captureSnapshot(
2223            String[] computedStyles, Boolean includePaintOrder, Boolean includeDOMRects, 
2224            Boolean includeBlendedBackgroundColors, Boolean includeTextColorOpacities
2225        )
2226    {
2227        // Exception-Check(s) to ensure that if any parameters which are not declared as
2228        // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw.
2229        
2230        if (computedStyles == null) THROWS.throwNPE("computedStyles");
2231        
2232        final int       webSocketID = 17003000 + counter++;
2233        final boolean[] optionals   = { false, true, true, true, true, };
2234        
2235        // Convert Method Parameters into JSON.  Build the JSON Request-Object (as a String)
2236        String requestJSON = WriteJSON.get(
2237            parameterTypes.get("captureSnapshot"),
2238            parameterNames.get("captureSnapshot"),
2239            optionals, webSocketID,
2240            "DOMSnapshot.captureSnapshot",
2241            computedStyles, includePaintOrder, includeDOMRects, includeBlendedBackgroundColors,
2242            includeTextColorOpacities
2243        );
2244        
2245        // 'JSON Binding' ... Converts Browser Response-JSON into Java-Type 'Ret2'
2246        Function<JsonObject, Ret2<DOMSnapshot.DocumentSnapshot[], String[]>> 
2247            responseProcessor = (JsonObject jo) -> new Ret2<>(
2248                (jo.getJsonArray("documents") == null)
2249                    ? null
2250                    : RJArrIntoStream.objArr(jo.getJsonArray("documents"), null, 0, DOMSnapshot.DocumentSnapshot.class).toArray(DOMSnapshot.DocumentSnapshot[]::new),
2251                (jo.getJsonArray("strings") == null)
2252                    ? null
2253                    : RJArrIntoStream.strArr(jo.getJsonArray("strings"), null, 0).toArray(String[]::new)
2254            );
2255        
2256        return new Script<>(webSocketID, requestJSON, responseProcessor);
2257    }
2258    
2259}