001package Torello.Browser.JsonAST;
002
003import Torello.JavaDoc.Annotations.LinkJavaSource;
004import Torello.JavaDoc.Annotations.JDHeaderBackgroundImg;
005
006import Torello.JSON.ReadJSON;
007import Torello.Java.ReadOnly.ReadOnlyList;
008
009import Torello.Java.Additional.Ret3;
010import Torello.Java.Additional.Ret4;
011
012import javax.json.JsonObject;
013
014import java.util.Objects;
015import java.io.Serializable;
016
017
018/**
019 * Maintains all relevant data and references for a single CDP Domain; you may view the complete
020 * list of domains by reveiwing the top level classes in either the
021 * 
022 * <A HREF='&#46;&#46;/&#46;&#46;/Browser/BrowserAPI/package-summary&#46;html'>
023 * Torello&#46;Browser&#46;BrowserAPI</A>
024 * 
025 * and
026 * 
027 * <A HREF='&#46;&#46;/&#46;&#46;/Browser/JavaScriptAPI/package-summary&#46;html'>
028 * Torello&#46;Browser&#46;JavaScriptAPI</A>
029 * 
030 * packages.  
031 * 
032 * <EMBED CLASS='external-html' DATA-FILE-ID=Domain>
033 * <EMBED CLASS='external-html' DATA-FILE-ID=AST_TREES>
034 */
035@JDHeaderBackgroundImg(EmbedTagFileID="AST_NODES_JDHBI")
036public class Domain implements Serializable, Comparable<Domain>
037{
038    // ********************************************************************************************
039    // ********************************************************************************************
040    // STATIC FINAL FIELDS
041    // ********************************************************************************************
042    // ********************************************************************************************
043
044
045    /* <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */
046    protected static final long serialVersionUID = 1;
047
048
049    // ********************************************************************************************
050    // ********************************************************************************************
051    // Constant & Final Instance-Fields (Set by the Constructor)
052    // ********************************************************************************************
053    // ********************************************************************************************
054
055    
056    /**
057     * Unique process-local identifier for this domain instance, assigned internally by
058     * {@code IDManager.nextID()}
059     */
060    public final int id = IDManager.nextID();
061
062    /** Domain name taken from the spec’s "domain" property (e.g., 'Network', 'Runtime', etc.). */
063    public final String name;
064
065    /** Human-readable description extracted from the spec; may be empty if not provided. */
066    public final String description;
067
068    /** Owning API this domain belongs to (Browser API or JavaScript API). */
069    public final API ownerAPI;
070
071    /**
072     * Complete list of top-level JSON property names present within the definition for this 
073     * domain's {@link JsonObject}.
074     */
075    public final ReadOnlyList<PropName> propNames;
076
077    /** {@code TRUE} if the spec marks this domain as experimental. */
078    public final boolean experimental;
079
080    /** {@code TRUE} if the spec marks this domain as deprecated. */
081    public final boolean deprecated;
082
083    /**
084     * All type definitions declared under this domain, parsed and extracted into {@link TypeNode}
085     * instances.
086     */
087    public final ReadOnlyList<TypeNode> types;
088
089    /**
090     * All type definitions declared under this domain, parsed and extracted into
091     * {@link CommandNode} instances.
092     */
093    public final ReadOnlyList<CommandNode> commands;
094
095    /**
096     * All type definitions declared under this domain, parsed and extracted into {@link EventNode}
097     * instances.
098     */
099    public final ReadOnlyList<EventNode> events;
100
101    /**
102     * Raw "dependencies" array preserved from the spec as {@code java.lang.String's}.  These 
103     * dependencies are not actually used anywhere in this code, but they are linked into actual 
104     * {@link Domain} references, and can be obtained by invoking {@link #getDependencies()}
105     */
106    public final ReadOnlyList<String> depAsStrs;
107
108
109    // ********************************************************************************************
110    // ********************************************************************************************
111    // Non-Final Instance-Fields: These are initialized **LATE**, by the Linker
112    // ********************************************************************************************
113    // ********************************************************************************************
114
115
116    /**
117     * The list of dependent domains.  This is a method, rather than a public {@code final} field,
118     * because it's value is computed during the "Linking Phase" of the Build-Mechanism.   Linking 
119     * is simply where the {@code String} {@code 'Network'} or {@code RunTime} is actually 
120     * converted to a pointer to the domain instance whose name is {@code 'Network'}.
121     * 
122     * <BR /><BR />This cannot be done inside the constructor, because it all domains must be first
123     * constructed before their refeences can be assigned to this field!  (Remember, {@code final}
124     * fields in a class must always be assigned befeore the object's constructor has finished.)
125     */
126
127    public ReadOnlyList<Domain> getDependencies() { return dependencies; }
128
129
130    // This has to be private, because it cannnot be "final".  Final Variables must be set at the 
131    // time the constructor is invoked.  This is just a list of Domain's, and therefore cannot be 
132    // set / assigned until the "Linking Phase".  The Linking Phase just converts a list  of 
133    // String's into a list of actual "Domain" References / Instances.  
134    // 
135    // Thusly, there is a public getter, and private field (and a package-private setter which the
136    // end user cannot access! - not very easily anyway, although I guess it is possible...)
137
138    private ReadOnlyList<Domain> dependencies = null;
139
140    // The Linker uses this / sets the "dependencies"
141    void setDependencies(final ReadOnlyList<Domain> dependencies)
142    { this.dependencies = dependencies; }
143
144
145    // ********************************************************************************************
146    // ********************************************************************************************
147    // Constructor
148    // ********************************************************************************************
149    // ********************************************************************************************
150
151
152    Domain(final API ownerAPI, final JsonObject jo)
153    {
154        this.ownerAPI = ownerAPI;
155
156
157        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
158        // Domain Name & List of Json Property-Names
159        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
160
161        // getString(JsonObject jo, String propertyName, boolean isOptional, boolean throwOnNull)
162        this.name = ReadJSON.getString(jo, "domain", false, true);
163
164        // The complete list of Json-Properties contained by this object (at the top level)
165        this.propNames = Helper$Misc.getPropNames(jo);
166
167
168        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
169        // JsonException - Expected Keys
170        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
171
172        Helper$CheckKeys.domainCheck(jo, name); 
173
174
175        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
176        // this.description & FLAGS
177        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
178
179        final Ret4<String, Boolean, Boolean, Boolean> ret4 =Helper$Misc.getDescAndFlags(jo);
180
181        this.description    = ret4.a;
182        // this.optional    = ret4.b; // Un Used for Domains
183        this.experimental   = ret4.c;
184        this.deprecated     = ret4.d;
185
186
187        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
188        // TCE Lists: TypeNode, CommandNode & EventNode
189        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
190
191        final Ret3
192        <
193            ReadOnlyList<TypeNode>,
194            ReadOnlyList<CommandNode>,
195            ReadOnlyList<EventNode>
196        >
197        r3 = Helper$GetTCELists.get(this, jo);
198
199        this.types          = r3.a;
200        this.commands       = r3.b;
201        this.events         = r3.c;
202
203
204        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
205        // The superfluous / unused "dependencies" array
206        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
207        // 
208        // This is not used by my code, anywhere...  But I'm parsing it, and leaving inside the 
209        // node anyways...  Not any extra amount of work, or anything too difficult.
210
211        this.depAsStrs = Helper$Misc.depAsStrs(jo);
212    }
213
214
215    // ********************************************************************************************
216    // ********************************************************************************************
217    // Comparable, Cloneable, Object
218    // ********************************************************************************************
219    // ********************************************************************************************
220
221
222    /** Generates a full {@code String} representation of {@code this} instance. */
223    @LinkJavaSource(handle="StringDomain")
224    public String toString()
225    { return StringDomain.get(this); }
226
227    /** Utilizes {@link #id this.id} as a hash; it is a unique value across the AST Tree. */
228    public int hashCode()
229    { return id; }
230
231    /**
232     * Checks {@link #name} fields, using the standard {@code String.compareTo} to produce a
233     * comparison value.
234     */
235    public int compareTo(final Domain other)
236    {
237        if (other == null)          return 1;
238        if (this.id == other.id)    return 0;
239
240        return (this.ownerAPI.id != other.ownerAPI.id)
241            ? this.ownerAPI.name.compareTo(other.ownerAPI.name)
242            : this.name.compareTo(other.name);
243    }
244
245    /** Checks {@link #id this.id} against {@code other.id} for equality. */
246    public boolean equals(final Object other)
247    {
248        if (other == null)              return false;
249        if (!(other instanceof Domain)) return false;
250        return this.id == ((Domain) other).id;
251    }
252}