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