1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
package Torello.Browser.JsonAST;

import Torello.JavaDoc.Annotations.LinkJavaSource;
import Torello.JavaDoc.Annotations.JDHeaderBackgroundImg;

import Torello.JSON.ReadJSON;
import Torello.Java.ReadOnly.ReadOnlyList;

import Torello.Java.Additional.Ret3;
import Torello.Java.Additional.Ret4;

import javax.json.JsonObject;

import java.util.Objects;
import java.io.Serializable;


/**
 * Maintains all relevant data and references for a single CDP Domain; you may view the complete
 * list of domains by reveiwing the top level classes in either the
 * 
 * <A HREF='&#46;&#46;/&#46;&#46;/Browser/BrowserAPI/package-summary&#46;html'>
 * Torello&#46;Browser&#46;BrowserAPI</A>
 * 
 * and
 * 
 * <A HREF='&#46;&#46;/&#46;&#46;/Browser/JavaScriptAPI/package-summary&#46;html'>
 * Torello&#46;Browser&#46;JavaScriptAPI</A>
 * 
 * packages.  
 * 
 * <EMBED CLASS='external-html' DATA-FILE-ID=Domain>
 * <EMBED CLASS='external-html' DATA-FILE-ID=AST_TREES>
 */
@JDHeaderBackgroundImg(EmbedTagFileID="AST_NODES_JDHBI")
public class Domain implements Serializable, Comparable<Domain>
{
    // ********************************************************************************************
    // ********************************************************************************************
    // STATIC FINAL FIELDS
    // ********************************************************************************************
    // ********************************************************************************************


    /* <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */
    protected static final long serialVersionUID = 1;


    // ********************************************************************************************
    // ********************************************************************************************
    // Constant & Final Instance-Fields (Set by the Constructor)
    // ********************************************************************************************
    // ********************************************************************************************

    
    /**
     * Unique process-local identifier for this domain instance, assigned internally by
     * {@code IDManager.nextID()}
     */
    public final int id = IDManager.nextID();

    /** Domain name taken from the spec’s "domain" property (e.g., 'Network', 'Runtime', etc.). */
    public final String name;

    /** Human-readable description extracted from the spec; may be empty if not provided. */
    public final String description;

    /** Owning API this domain belongs to (Browser API or JavaScript API). */
    public final API ownerAPI;

    /**
     * Complete list of top-level JSON property names present within the definition for this 
     * domain's {@link JsonObject}.
     */
    public final ReadOnlyList<PropName> propNames;

    /** {@code TRUE} if the spec marks this domain as experimental. */
    public final boolean experimental;

    /** {@code TRUE} if the spec marks this domain as deprecated. */
    public final boolean deprecated;

    /**
     * All type definitions declared under this domain, parsed and extracted into {@link TypeNode}
     * instances.
     */
    public final ReadOnlyList<TypeNode> types;

    /**
     * All type definitions declared under this domain, parsed and extracted into
     * {@link CommandNode} instances.
     */
    public final ReadOnlyList<CommandNode> commands;

    /**
     * All type definitions declared under this domain, parsed and extracted into {@link EventNode}
     * instances.
     */
    public final ReadOnlyList<EventNode> events;

    /**
     * Raw "dependencies" array preserved from the spec as {@code java.lang.String's}.  These 
     * dependencies are not actually used anywhere in this code, but they are linked into actual 
     * {@link Domain} references, and can be obtained by invoking {@link #getDependencies()}
     */
    public final ReadOnlyList<String> depAsStrs;


    // ********************************************************************************************
    // ********************************************************************************************
    // Non-Final Instance-Fields: These are initialized **LATE**, by the Linker
    // ********************************************************************************************
    // ********************************************************************************************


    /**
     * The list of dependent domains.  This is a method, rather than a public {@code final} field,
     * because it's value is computed during the "Linking Phase" of the Build-Mechanism.   Linking 
     * is simply where the {@code String} {@code 'Network'} or {@code RunTime} is actually 
     * converted to a pointer to the domain instance whose name is {@code 'Network'}.
     * 
     * <BR /><BR />This cannot be done inside the constructor, because it all domains must be first
     * constructed before their refeences can be assigned to this field!  (Remember, {@code final}
     * fields in a class must always be assigned befeore the object's constructor has finished.)
     */

    public ReadOnlyList<Domain> getDependencies() { return dependencies; }


    // This has to be private, because it cannnot be "final".  Final Variables must be set at the 
    // time the constructor is invoked.  This is just a list of Domain's, and therefore cannot be 
    // set / assigned until the "Linking Phase".  The Linking Phase just converts a list  of 
    // String's into a list of actual "Domain" References / Instances.  
    // 
    // Thusly, there is a public getter, and private field (and a package-private setter which the
    // end user cannot access! - not very easily anyway, although I guess it is possible...)

    private ReadOnlyList<Domain> dependencies = null;

    // The Linker uses this / sets the "dependencies"
    void setDependencies(final ReadOnlyList<Domain> dependencies)
    { this.dependencies = dependencies; }


    // ********************************************************************************************
    // ********************************************************************************************
    // Constructor
    // ********************************************************************************************
    // ********************************************************************************************


    Domain(final API ownerAPI, final JsonObject jo)
    {
        this.ownerAPI = ownerAPI;


        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
        // Domain Name & List of Json Property-Names
        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

        // getString(JsonObject jo, String propertyName, boolean isOptional, boolean throwOnNull)
        this.name = ReadJSON.getString(jo, "domain", false, true);

        // The complete list of Json-Properties contained by this object (at the top level)
        this.propNames = Helper$Misc.getPropNames(jo);


        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
        // JsonException - Expected Keys
        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

        Helper$CheckKeys.domainCheck(jo, name); 


        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
        // this.description & FLAGS
        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

        final Ret4<String, Boolean, Boolean, Boolean> ret4 =Helper$Misc.getDescAndFlags(jo);

        this.description    = ret4.a;
        // this.optional    = ret4.b; // Un Used for Domains
        this.experimental   = ret4.c;
        this.deprecated     = ret4.d;


        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
        // TCE Lists: TypeNode, CommandNode & EventNode
        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

        final Ret3
        <
            ReadOnlyList<TypeNode>,
            ReadOnlyList<CommandNode>,
            ReadOnlyList<EventNode>
        >
        r3 = Helper$GetTCELists.get(this, jo);

        this.types          = r3.a;
        this.commands       = r3.b;
        this.events         = r3.c;


        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
        // The superfluous / unused "dependencies" array
        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
        // 
        // This is not used by my code, anywhere...  But I'm parsing it, and leaving inside the 
        // node anyways...  Not any extra amount of work, or anything too difficult.

        this.depAsStrs = Helper$Misc.depAsStrs(jo);
    }


    // ********************************************************************************************
    // ********************************************************************************************
    // Comparable, Cloneable, Object
    // ********************************************************************************************
    // ********************************************************************************************


    /** Generates a full {@code String} representation of {@code this} instance. */
    @LinkJavaSource(handle="StringDomain")
    public String toString()
    { return StringDomain.get(this); }

    /** Utilizes {@link #id this.id} as a hash; it is a unique value across the AST Tree. */
    public int hashCode()
    { return id; }

    /**
     * Checks {@link #name} fields, using the standard {@code String.compareTo} to produce a
     * comparison value.
     */
    public int compareTo(final Domain other)
    {
        if (other == null)          return 1;
        if (this.id == other.id)    return 0;

        return (this.ownerAPI.id != other.ownerAPI.id)
            ? this.ownerAPI.name.compareTo(other.ownerAPI.name)
            : this.name.compareTo(other.name);
    }

    /** Checks {@link #id this.id} against {@code other.id} for equality. */
    public boolean equals(final Object other)
    {
        if (other == null)              return false;
        if (!(other instanceof Domain)) return false;
        return this.id == ((Domain) other).id;
    }
}