001package Torello.Browser.JsonAST;
002
003import Torello.Browser.JsonAST.TypeNode;
004
005import Torello.Java.ReadOnly.ReadOnlyList;
006import Torello.Java.ReadOnly.ReadOnlySet;
007
008import Torello.Java.ReadOnly.ROTreeSetBuilder;
009import Torello.Java.ReadOnly.ROArrayListBuilder;
010
011import Torello.Java.UnreachableError;
012import Torello.Java.StrCSV;
013import Torello.Java.StrPrint;
014
015/**
016 * <EMBED CLASS='external-html' DATA-FILE-ID=INFO_DATA>
017 * @see ExtraData
018 * @see SERIALIZED_AST#browserDat
019 * @see SERIALIZED_AST#jsDat
020 */
021@Torello.JavaDoc.Annotations.JDHeaderBackgroundImg(EmbedTagFileID="SERIALIZER_JDHBI")
022public class InfoData implements java.io.Serializable
023{
024    static InfoData.Builder builder() { return new InfoData.Builder(); }
025
026    /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */
027    protected static final long serialVersionUID = 1;
028
029
030    // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
031    // Lists - The names of these lists *OUGHT TO* explain exatly what they are lists of ...
032    // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
033
034    /**
035     * <EMBED CLASS='external-html' DATA-FILE-ID=ID_ELIM_TYPE_NODES>
036     * @see #simpleTypeNodes
037     * @see #enumValTypeNodes
038     */
039    public final ReadOnlyList<TypeNode> eliminatedTypeNodes;
040
041    /** <EMBED CLASS='external-html' DATA-FILE-ID=ID_SIMPLE_TYPE_NODES> */
042    public final ReadOnlyList<TypeNode> simpleTypeNodes;
043
044    /** <EMBED CLASS='external-html' DATA-FILE-ID=ID_ENUM_VAL_TYPE_NODES> */
045    public final ReadOnlyList<TypeNode> enumValTypeNodes;
046
047    /** <EMBED CLASS='external-html' DATA-FILE-ID=ID_MARKER_EVENT_NODES> */
048    public final ReadOnlyList<EventNode> markerEventNodes;
049
050
051    // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
052    // Sets - The names of these sets *OUGHT TO* explain exatly what they are lists of ...
053    // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
054
055    /**
056     * <EMBED CLASS='external-html' DATA-FILE-ID=ID_HAS_ENUM_STR_LISTS>
057     * @see Entity#ownerDomain
058     * @see #enumValTypeNodes
059     */
060    public final ReadOnlySet<Domain> hasEnumStrLists;
061
062    /**
063     * The list of domains which have at least one zero-property type (and were eliminated during
064     * the code generation step).
065     */
066    public final ReadOnlySet<Domain> hasSimpleTypes;
067
068    /**
069     * <EMBED CLASS='external-html' DATA-FILE-ID=ID_HAS_MARKER_EVENTS>
070     * @see Entity#ownerDomain
071     * @see #markerEventNodes
072     */
073    public final ReadOnlySet<Domain> hasMarkerEvents;
074
075    /**
076     * The set of all domains which have actual nested java inner classes defined within them.
077     * There are relatively few domains in the CDP API that do not actually define any types, though
078     * there are some.
079     * 
080     * <BR /><BR />
081     * In the most recent parsing and generation of the "Browser API" from CDP, 41 out of the 47
082     * Domains have actual, reified, events.  You may see the {@link #toString() toString Output}
083     * for this class by clicking the link.
084     */
085    public final ReadOnlySet<Domain> hasReifiedTypes;
086
087    /**
088     * This should list all domains that have commands which return more than one value as a result
089     * of their invocation.  Rather than return tuples of results, a dedicated nested-inner type is
090     * created for any CDP command that needs to actually return more than one value.
091     */
092    public final ReadOnlySet<Domain> hasReifiedReturnTypes;
093
094    /**
095     * The set of all domains which have actual nested java inner classes defined within them.
096     * Event inner classes are not actually defined in any way that is different from standard 
097     * inner types.  Instead, they are just listed on their respective Java-Doc Pages as "Event 
098     * Classes" which are only generated when the CDP API actually fires an event for them.
099     * 
100     * <BR /><BR />
101     * In the most recent parsing and generation of the "Browser API" from CDP, 33 out of the 47
102     * Domains have actual, reified, events.  You may see the {@link #toString() toString Output}
103     * for this class by clicking the link.
104     */
105    public final ReadOnlySet<Domain> hasReifiedEvents;
106
107
108    // ********************************************************************************************
109    // ********************************************************************************************
110    // Constructor
111    // ********************************************************************************************
112    // ********************************************************************************************
113
114
115    InfoData(
116            final ReadOnlyList<TypeNode>    eliminatedTypeNodes,
117            final ReadOnlyList<TypeNode>    simpleTypeNodes,
118            final ReadOnlyList<TypeNode>    enumValTypeNodes,
119            final ReadOnlyList<EventNode>   markerEventNodes,
120
121            final ReadOnlySet<Domain>       hasEnumStrLists,
122            final ReadOnlySet<Domain>       hasSimpleTypes,
123            final ReadOnlySet<Domain>       hasMarkerEvents,
124
125            final ReadOnlySet<Domain>       hasReifiedTypes,
126            final ReadOnlySet<Domain>       hasReifiedReturnTypes,
127            final ReadOnlySet<Domain>       hasReifiedEvents
128        )
129    {
130        this.eliminatedTypeNodes    = eliminatedTypeNodes;
131        this.simpleTypeNodes        = simpleTypeNodes;
132        this.enumValTypeNodes       = enumValTypeNodes;
133        this.markerEventNodes       = markerEventNodes;
134
135        this.hasEnumStrLists    = hasEnumStrLists;
136        this.hasSimpleTypes     = hasSimpleTypes;
137        this.hasMarkerEvents    = hasMarkerEvents;
138
139        this.hasReifiedTypes        = hasReifiedTypes;
140        this.hasReifiedReturnTypes  = hasReifiedReturnTypes;
141        this.hasReifiedEvents       = hasReifiedEvents;
142    }
143
144
145    // ********************************************************************************************
146    // ********************************************************************************************
147    // toString
148    // ********************************************************************************************
149    // ********************************************************************************************
150
151
152    /**
153     * Generates a {@code String} representation of the contents of this {@code 'InfoData'} 
154     * instance.  The only two instances of {@code 'InfoData'} which are generated are the one for
155     * the "Browser API" along with the instance which represents Google's "JavaScript API"
156     * 
157     * <BR /><BR />
158     * The "See Also" link below provides a direct link to the two fields within the class 
159     * {@link SERIALIZED_AST} which contains a reference / pointer to an instance of this class.
160     * 
161     * @return A {@code String} representation / summary of one of the two API's.
162     * 
163     * @see SERIALIZED_AST#browserDat
164     * @see SERIALIZED_AST#jsDat
165     */
166    public String toString()
167    {
168        return
169            "{\n" +
170            "    this.hasEnumStrLists:"     + list(this.hasEnumStrLists) +
171            "    this.hasSimpleTypes:"      + list(this.hasSimpleTypes) +
172            "    this.hasMarkerEvents:"     + list(this.hasMarkerEvents) +
173            "    this.hasReifiedTypes:"     + list(this.hasReifiedTypes) +
174            "    this.hasReifiedEvents:"    + list(this.hasReifiedEvents) +
175            '\n' +
176            "    this.eliminatedTypeNodes.size(): " + this.eliminatedTypeNodes.size()       + '\n' +
177            "    this.simpleTypeNodes.size():     " + this.simpleTypeNodes.size()           + '\n' +
178            "    this.enumValTypeNodes.size():    " + this.enumValTypeNodes.size()          + '\n' +
179            "    this.markerEventNodes.size():    " + this.markerEventNodes.size()          + '\n' +
180            '\n' +
181            "    this.hasEnumStrLists.size():       " + this.hasEnumStrLists.size()         + '\n' +
182            "    this.hasSimpleTypes.size():        " + this.hasSimpleTypes.size()          + '\n' +
183            "    this.hasMarkerEvents.size():       " + this.hasMarkerEvents.size()         + '\n' +
184            'n' +
185            "    this.hasReifiedTypes.size():       " + this.hasReifiedTypes.size()         + '\n' +
186            "    this.hasReifiedReturnTypes.size(): " + this.hasReifiedReturnTypes.size()   + '\n' +
187            "    this.hasReifiedEvents.size():      " + this.hasReifiedEvents.size()        + '\n' +
188            "}\n";
189    }
190
191    private static String list(final ReadOnlySet<Domain> domainList)
192    {
193        final String csv =
194            '\n' +
195            "        " +
196            StrCSV.toCSV(domainList, (Domain d) -> d.name, true, null) +
197            '\n' +
198            '\n';
199
200        return StrPrint.wrapToIndentation(csv, 100);
201    }
202
203
204    // ********************************************************************************************
205    // ********************************************************************************************
206    // Builder
207    // ********************************************************************************************
208    // ********************************************************************************************
209
210
211    // When complicated data gets moving there is nothing more valuable than enuring that the code 
212    // which is going to "use" your data (Here, AST data) - is final, immutable and read only.
213    // 
214    // Using this "Builder" design pattern means that the "InfoData" class that is saved to disk 
215    // so that the Code Generator can later retrieve it - CONTAINS NOTHING BUT FINAL, IMMUTABLE AND
216    // READ-ONLY DATA.  
217
218    static class Builder
219    {
220        private Builder() { }
221
222
223        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
224        // Lists ==> The exact same lists as above, but as "ReadOnlyList Builders" instead
225        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
226
227        private final ROArrayListBuilder<TypeNode> eliminatedTypeNodesROALB =
228            new ROArrayListBuilder<>();
229
230        private final ROArrayListBuilder<TypeNode> simpleTypeNodesROALB =
231            new ROArrayListBuilder<>();
232
233        private final ROArrayListBuilder<TypeNode> enumValTypeNodesROALB =
234            new ROArrayListBuilder<>();
235
236        private final ROArrayListBuilder<EventNode> markerEventNodesROALB =
237            new ROArrayListBuilder<>();
238
239
240        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
241        // Sets ==> The exact same sets as above, but as "ReadOnlySet Builders" instead
242        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
243
244        private final ROTreeSetBuilder<Domain> hasEnumStrListsROTSB =
245            new ROTreeSetBuilder<>();
246
247        private final ROTreeSetBuilder<Domain> hasSimpleTypesROTSB =
248            new ROTreeSetBuilder<>();
249
250        private final ROTreeSetBuilder<Domain> hasMarkerEventsROTSB =
251            new ROTreeSetBuilder<>();
252
253
254        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
255        // More Sets ==> Specifically for the "Reified Nested Types"
256        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
257
258        private final ROTreeSetBuilder<Domain> hasReifiedTypesROTSB =
259            new ROTreeSetBuilder<>();
260
261        private final ROTreeSetBuilder<Domain> hasReifiedReturnTypesROTSB =
262            new ROTreeSetBuilder<>();
263
264        private final ROTreeSetBuilder<Domain> hasReifiedEventsROTSB =
265            new ROTreeSetBuilder<>();
266        
267
268        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
269        // Builder Methods that "add stuff" into this builder!  (How the builder "builds")
270        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
271
272        void enumValType(final TypeNode tn)
273        {
274            if (tn.enumVals == null)    throw new UnreachableError();
275            if (tn.isReifiedInnerClass) throw new UnreachableError();
276
277            enumValTypeNodesROALB.add(tn);
278            eliminatedTypeNodesROALB.add(tn);
279            hasEnumStrListsROTSB.add(tn.ownerDomain);
280        }
281
282        void simpleType(final TypeNode tn)
283        {
284            if (tn.isReifiedInnerClass) throw new UnreachableError();
285            if (tn.properties != null)  throw new UnreachableError();
286
287            simpleTypeNodesROALB.add(tn);
288            eliminatedTypeNodesROALB.add(tn);
289            hasSimpleTypesROTSB.add(tn.ownerDomain);
290        }
291
292        void markerEvent(final EventNode en)
293        {
294            if (en.parameters != null) throw new UnreachableError();
295            markerEventNodesROALB.add(en);
296            hasMarkerEventsROTSB.add(en.ownerDomain);
297        }
298
299        void reifiedInnerType(final TypeNode tn)
300        {
301            if (! tn.isReifiedInnerClass)   throw new UnreachableError();
302            if (tn.properties == null)      throw new UnreachableError();
303            if (tn.properties.size() == 0)  throw new UnreachableError();
304
305            hasReifiedTypesROTSB.add(tn.ownerDomain);
306        }
307
308        void reifiedReturnType(final CommandNode cn)
309        {
310            if (! cn.hasReifiedRetInnerClass)   throw new UnreachableError();
311            if (cn.returns == null)             throw new UnreachableError();
312            if (cn.returns.size() <= 1)         throw new UnreachableError();
313
314            hasReifiedReturnTypesROTSB.add(cn.ownerDomain);
315        }
316
317        void reifiedEvent(final EventNode en)
318        {
319            if (! en.isReifiedInnerClass)   throw new UnreachableError();
320            if (en.parameters == null)      throw new UnreachableError();
321            if (en.parameters.size() == 0)  throw new UnreachableError();
322
323            hasReifiedEventsROTSB.add(en.ownerDomain);
324        }
325
326        InfoData build()
327        {
328            return new InfoData(
329                eliminatedTypeNodesROALB.build(),
330                simpleTypeNodesROALB.build(),
331                enumValTypeNodesROALB.build(),
332                markerEventNodesROALB.build(),
333
334                hasEnumStrListsROTSB.build(),
335                hasSimpleTypesROTSB.build(),
336                hasMarkerEventsROTSB.build(),
337
338                hasReifiedTypesROTSB.build(),
339                hasReifiedReturnTypesROTSB.build(),
340                hasReifiedEventsROTSB.build()
341            );
342        }
343    }
344
345}