001package Torello.HTML;
002
003/**
004 * This class is mostly a wrapper for class <CODE>java&#46;lang&#46;String</CODE>, and serves as
005 * the abstract parent of the three types of HTML elements offered by the Java HTML Library.
006 * 
007 * <BR /><BR /><EMBED CLASS="external-html" DATA-FILE-ID="N">
008 * <EMBED CLASS="external-html" DATA-FILE-ID="HTMLNODESUB">
009 */
010public abstract class HTMLNode implements CharSequence, java.io.Serializable, Cloneable
011{
012    /** <EMBED CLASS="external-html" DATA-FILE-ID="SVUID"> */
013    public static final long serialVersionUID = 1;
014
015    /**
016     * This is an immutable field.  It stores the complete contents of an HTML node.  It can be 
017     * either the <B>"textual contents"</B>
018     * of an HTML {@code TagNode}, or the text (directly) of the text-inside of an HTML page!
019     * 
020     * <BR /><BR />
021     * <B>FOR INSTANCE:</B>
022     * 
023     * <BR /><BR /><UL CLASS="JDUL">
024     * <LI>A subclass of HTMLNode - <CODE>TagNode</CODE> - could contain the String
025     *      <SPAN STYLE="color: red;">&lt;SPAN STYLE="CSS INFO"&gt;"</SPAN>
026     *      <I>inside this <CODE><B>str field</CODE></B> here.</I>
027     * </LI>
028     * <LI> The other sub-class of HTML - <CODE>TextNode</CODE> - could contain the {@code String}
029     *      <SPAN STYLE="color: red;">"This is a news-page from www.Gov.CN Chinese Government
030     *      Portal."</SPAN> <I>inside this <CODE><B>str field</CODE></B> here.</I>
031     * </LI>
032     * </UL>
033     * 
034     * <BR /><B>NOTE:</B> Because sub-classes of {@code HTMLNode} are all immutable, generally,
035     * if you wish to change the contents of an HTML page, a programmer is required to create new
036     * nodes, rather than changing these fields.
037     */
038    public final String str;
039
040    /**
041     * Constructor that builds a new {@code HTMLNode}
042     * 
043     * @param s A valid string of an HTML element.
044     */
045    protected HTMLNode(String s) { this.str = s; }
046
047    /**
048     * Java's hash-code requirement.
049     * 
050     * <BR /><BR /><B><SPAN STYLE="color: red;">FINAL METHOD:</B></SPAN> This method is final, and 
051     * cannot be modified by sub-classes.
052     * 
053     * @return A hash-code that may be used when storing this node in a java sorted-collection.
054     */
055    public final int hashCode() { return this.str.hashCode(); }
056
057    /**
058     * Java's {@code public boolean equals(Object o)} requirements.
059     * 
060     * <BR /><BR /><B><SPAN STYLE="color: red;">FINAL METHOD:</B></SPAN> This method is final, and 
061     * cannot be modified by sub-classes.
062     * 
063     * @param o This may be any Java Object, but only ones of {@code 'this'} type whose
064     * internal-values are identical will cause this method to return <B>TRUE</B>.
065     * 
066     * @return <B>TRUE</B> If {@code 'this'} equals another object {@code HTMLNode.}
067     */
068    public final boolean equals(Object o)
069    {
070        return      (this == o)
071                || (    (o != null)
072                    &&  (this.getClass().equals(o.getClass()))
073                    &&  (((HTMLNode) o).str.equals(this.str)));
074    }
075
076    /**
077     * Sub-classes of {@code HTMLNode} must be {@code Cloneable.}
078     * 
079     * @return Must return an identical copy of {@code 'this'} node.  The object reference cannot
080     * be {@code 'this'} reference.
081     */
082    public abstract HTMLNode clone();
083
084
085    // **********************************************************************************************
086    // CharSequence Methods
087    // **********************************************************************************************
088
089    /**
090     * Java's {@code toString()} requirement.
091     * 
092     * <BR /><BR /><B><SPAN STYLE="color: red;">FINAL METHOD:</B></SPAN> This method is final, and
093     * cannot be modified by sub-classes.
094     * 
095     * @return A {@code String}-representation of this {@code HTMLNode.}
096     */
097    public final String toString() { return this.str; }
098
099    /**
100     * Returns the char value at the specified index of the field: {@code public final String str}.
101     * An index ranges from {@code '0'} (zero) to {@code HTMLNode.str.length() - 1.} The first 
102     * {@code char} value of the sequence is at index zero, the next at index one, and so on, as 
103     * for array indexing.
104     * 
105     * <BR /><BR /><B>NOTE:</B> If the {@code char} value specified by the index is a surrogate, 
106     * the surrogate value is returned.
107     * 
108     * <BR /><BR /><B><SPAN STYLE="color: red;">FINAL METHOD:</B></SPAN> This method is final, and 
109     * cannot be modified by sub-classes.
110     * 
111     * @param index The index of the {@code char} value to be returned
112     * 
113     * @return The specified {@code char} value
114     */
115    public final char charAt(int index) { return str.charAt(index); }
116
117    /**
118     * Returns the length of the field {@code public final String str}. 
119     * The length is the number of 16-bit chars in the sequence.
120     * 
121     * <BR /><BR /><B><SPAN STYLE="color: red;">FINAL METHOD:</B></SPAN> This method is final, and 
122     * cannot be modified by sub-classes.
123     * 
124     * @return the number of {@code chars} in {@code this.str}
125     */
126    public final int length() { return str.length(); }
127
128    /**
129     * Returns a {@code CharSequence} that is a subsequence of the {@code public final String str}
130     * field of {@code 'this' HTMLNode}.
131     * The subsequence starts with the {@code char} value at the specified index and ends with the 
132     * {@code char} value at index {@code end - 1.} The length (in chars) of the returned sequence
133     * is {@code end - start},  so if {@code start == end} then an empty sequence is returned.
134     * 
135     * <BR /><BR /><B><SPAN STYLE="color: red;">FINAL METHOD:</B></SPAN> This method is final, and 
136     * cannot be modified by sub-classes.
137     * 
138     * @param start The start index, inclusive
139     * @param end The end index, exclusive
140     * 
141     * @return The specified subsequence
142     */
143    public final CharSequence subSequence(int start, int end)
144    { return str.substring(start, end); }
145
146
147    // ********************************************************************************************
148    // ********************************************************************************************
149    // 'is' Optimization Methods
150    // ********************************************************************************************
151    // ********************************************************************************************
152
153
154    /**
155     * This method will return <B>TRUE</B> for any instance of {@code 'CommentNode'}.
156     *
157     * <BR /><BR />The purpose of this method is to efficiently return <B>TRUE</B> whenever
158     * an instance of {@code 'HTMLNode'} should be checked to see if it is actually an inherited
159     * instance of {@code CommentNode}.  This is (marginally) more efficient than using the Java
160     * {@code 'instanceof'} operator.
161     *
162     * @return This (top-level inheritance-tree) method always returns <B>FALSE</B>.  The 
163     * {@code '.java'} file for {@code class CommentNode} overrides this method, and returns
164     * <B>TRUE</B>.
165     * 
166     * @see CommentNode#isCommentNode()
167     */
168    public boolean isCommentNode()
169    {
170        // This method will *only* be over-ridden by subclass CommentNode, where it shall return
171        // TRUE.  Neither class TextNode, nor class TagNode will over-ride this method.
172
173        return false;
174    }
175
176    /**
177     * This method will return <B>TRUE</B> for any instance of {@code 'TextNode'}.
178     *
179     * <BR /><BR />The purpose of this method is to efficiently return <B>TRUE</B> whenever
180     * an instance of {@code 'HTMLNode'} should be checked to see if it is actually an inherited
181     * instance of {@code TextNode}.  This is (marginally) more efficient than using the Java
182     * {@code 'instanceof'} operator.
183     *
184     * @return This (top-level inheritance-tree) method always returns <B>FALSE</B>.  The 
185     * {@code '.java'} file for {@code class TextNode} overrides this method, and returns
186     * <B>TRUE</B>.
187     * 
188     * @see TextNode#isTextNode()
189     */
190    public boolean isTextNode()
191    {
192        // This method will *only* be over-ridden by subclass CommentNode, where it shall return
193        // TRUE.  Neither class TextNode, nor class TagNode will over-ride this method.
194
195        return false;
196    }
197
198    /**
199     * This method will return <B>TRUE</B> for any instance of {@code 'TagNode'}.
200     *
201     * <BR /><BR />The purpose of this method is to efficiently return <B>TRUE</B> whenever
202     * an instance of {@code 'HTMLNode'} should be checked to see if it is actually an inherited
203     * instance of {@code TagNode}.  This is (marginally) more efficient than using the Java
204     * {@code 'instanceof'} operator.
205     *
206     * @return This (top-level inheritance-tree) method always returns <B>FALSE</B>.  The 
207     * {@code '.java'} file for {@code class TagNode} overrides this method, and returns
208     * <B>TRUE</B>.
209     * 
210     * @see TagNode#isTagNode()
211     */
212    public boolean isTagNode()
213    {
214        // This method will *only* be over-ridden by subclass TagNode, where it shall return
215        // TRUE.  Neither class TextNode, nor class CommentNode will over-ride this method.
216
217        return false;
218    }
219
220
221    // ********************************************************************************************
222    // ********************************************************************************************
223    // TagNode Optimization Methods
224    // ********************************************************************************************
225    // ********************************************************************************************
226
227
228    /**
229     * <B STYLE='color:red;'>PWA: Open Tag, 'Possibly With Attributes'</B>
230     * 
231     * This method is offered as an <I><B>optimization tool for quickly finding</B></I> HTML Tag's
232     * that have attributes inside of a search-loop.  Since this class, class {@code HTMLNode}, is
233     * the abstract parent of all three HTML element-types, and since <B>{@link TagNode} is the
234     * only one of those three that overrides this method</B>, the "optimization" acheived is that,
235     * by default, most concrete-instances of this abstract-parent class {@code HTMLNode} <I>will
236     * immediately return null</I> when queried by a search-loop - which makes the process of
237     * finding {@code TagNode's} with a particular attribute much more efficient.
238     *
239     * <BR /><BR />The purpose of this method is to quickly return a node that has been cast to
240     * an instance of {@code TagNode}, if it is, indeed, a {@code TagNode} <B><I>and if</I></B> it
241     * has an internal-{@code String} long-enough to possibly contain attributes (inner-tags).
242     * 
243     * @return This method shall always return null, unless this method has been overridden by a
244     * sub-class.  Only {@code TagNode} overrides this method, and if the particular instance of
245     * {@code TagNode} being tested contains an internal {@code 'str'} field that's long-enough to
246     * have attributes (and it's {@code 'isClosing'} field is {@code FALSE}), <B>then and only
247     * then</B> shall this return a non-null value.
248     * 
249     * <BR /><BR />When the overridden {@code TagNode} sub-class returns a non-null result, that
250     * value will <B>always be equal to {@code 'this'}</B>
251     * 
252     * <BR /><BR /><B STYLE='color: red'>AGAIN:</B> For overriding sub-class {@code TagNode},
253     * when this method returns a non-null value (always {@code 'this'} instance), it will be
254     * because the internal-{@code String} is actually long enough to be worthy of being tested for
255     * attribute / inner-tag <B STYLE='color:red'>key-value</B> pairs.
256     * 
257     * @see TagNode#openTagPWA()
258     */
259    public TagNode openTagPWA()
260    {
261        // This method will *only* be over-ridden by subclass TagNode.
262        // For instances of inheriting class TextNode and CommentNode, this always returns null.
263        // In 'TagNode' this method returns true based on the 'isClosing' field from that class,
264        // and the length of the 'str' field from this class.
265
266        return null;
267    }
268
269    /**
270     * This method is offered as an <I><B>optimization tool for quickly finding</B></I> HTML Tag's
271     * that are Opening-Tags.  Since this class, class {@code HTMLNode}, is the abstract parent of
272     * all three HTML element-types, and since <B>{@link TagNode} is the only one of those three
273     * that overrides this method</B>, the "optimization" acheived is that, by default, most
274     * concrete-instances of this abstract-parent class {@code HTMLNode} <I>will immediately return
275     * null</I> when queried by a search-loop - which makes the process of finding opening
276     * {@code TagNode's} more efficient.
277     *
278     * @return This method shall always return null, unless this method has been overridden by a
279     * sub-class.  Only {@code TagNode} overrides this method, and if the particular instance of
280     * {@code TagNode} being tested has a {@code FALSE} value assigned to its {@code 'isClosing'}
281     * field <B>then and only then</B> shall this return a non-null value.
282     * 
283     * <BR /><BR />When the overridden {@code TagNode} sub-class returns a non-null result, that
284     * value will <B>always be equal to {@code 'this'}</B>
285     * 
286     * @see TagNode#openTag()
287     */
288    public TagNode openTag()
289    {
290        // This method will *only* be over-ridden by subclass TagNode.
291        // For instances of inheriting class TextNode and CommentNode, this always returns null.
292        // In 'TagNode' this method returns true based on that class 'isClosing' field.
293
294        return null;
295    }
296
297
298    // ********************************************************************************************
299    // ********************************************************************************************
300    // 'if' loop-optimizers
301    // ********************************************************************************************
302    // ********************************************************************************************
303
304
305    /**
306     * <B STYLE='color: red;'>Loop Optimization Method</B>
307     * 
308     * <BR /><BR />When this method is invoked on an instance of sub-class {@link TagNode},
309     * this method produces {@code 'this'} instance.
310     * 
311     * @return This method is overriden by sub-class {@code TagNode}, and in that class, this
312     * method simply returns {@code 'this'}.  The other sub-classes of this ({@code abstract})
313     * class inherit this version of this method, and therefore return null.
314     * 
315     * @see TagNode#ifTagNode()
316     */
317    public TagNode ifTagNode()
318    {
319        // This method will *only* be over-ridden by subclass TagNode, where it shall return
320        // 'this'.  Neither class TextNode, nor class CommentNode will over-ride this method.
321
322        return null;
323    }
324
325    /**
326     * <B STYLE='color: red;'>Loop Optimization Method</B>
327     * 
328     * <BR /><BR />When this method is invoked on an instance of sub-class {@link TextNode},
329     * this method produces {@code 'this'} instance.
330     * 
331     * @return This method is overriden by sub-class {@code TextNode}, and in that class, this
332     * method simply returns {@code 'this'}.  The other sub-classes of this ({@code abstract})
333     * class inherit this version of this method, and therefore return null.
334     * 
335     * @see TextNode#ifTextNode()
336     */
337    public TextNode ifTextNode()
338    {
339        // This method will *only* be over-ridden by subclass TextNode, where it shall return
340        // 'this'.  Neither class TagNode, nor class CommentNode will over-ride this method.
341
342        return null;
343    }
344
345    /**
346     * <B STYLE='color: red;'>Loop Optimization Method</B>
347     * 
348     * <BR /><BR />When this method is invoked on an instance of sub-class {@link CommentNode},
349     * this method produces {@code 'this'} instance.
350     * 
351     * @return This method is overriden by sub-class {@code CommentNode}, and in that class, this
352     * method simply returns {@code 'this'}.  The other sub-classes of this ({@code abstract})
353     * class inherit this version of this method, and therefore return null.
354     * 
355     * @see CommentNode#ifCommentNode()
356     */
357    public CommentNode ifCommentNode()
358    {
359        // This method will *only* be over-ridden by subclass CommentNode, where it shall return
360        // 'this'.  Neither class TagNode, nor class TextNode will over-ride this method.
361
362        return null;
363    }
364
365
366    // ********************************************************************************************
367    // ********************************************************************************************
368    // 'is' loop-optimizers
369    // ********************************************************************************************
370    // ********************************************************************************************
371
372
373    /**
374     * Compile-Time "Syntactic Sugar" for casting an {@code HTMLNode} to a {@code TagNode}.
375     * 
376     * @return Simply returns {@code 'this'} instance.  (Note that the method
377     * {@code Class.cast(Object)} <I>doesn't actually do *anything*</I>, other than provide the
378     * compile-time logic some 'proof' in its type-analysis)
379     * 
380     * @throws ClassCastException <B STYLE='color: red;'>IMPORTANT:</B> If the instance is a
381     * {@link TextNode} or {@code CommentNode}, rather than a {@link TagNode}, then (naturally) the
382     * JVM will immediately throw a casting exception.
383     */
384    public TagNode asTagNode() { return TagNode.class.cast(this); }
385
386    /**
387     * Compile-Time "Syntactic Sugar" for casting an {@code HTMLNode} to a {@code TextNode}.
388     * 
389     * @return Simply returns {@code 'this'} instance.  (Note that the method
390     * {@code Class.cast(Object)} <I>doesn't actually do *anything*</I>, other than provide the
391     * compile-time logic some 'proof' in its type-analysis)
392     * 
393     * @throws ClassCastException <B STYLE='color: red;'>IMPORTANT:</B> If the instance is a
394     * {@link TagNode} or {@code CommentNode}, rather than a {@link TextNode}, then (naturally) the
395     * JVM will immediately throw a casting exception.
396     */
397    public TextNode asTextNode() { return TextNode.class.cast(this); }
398
399    /**
400     * Compile-Time "Syntactic Sugar" for casting an {@code HTMLNode} to a {@code CommentNode}.
401     * 
402     * @return Simply returns {@code 'this'} instance.  (Note that the method
403     * {@code Class.cast(Object)} <I>doesn't actually do *anything*</I>, other than provide the
404     * compile-time logic some 'proof' in its type-analysis)
405     * 
406     * @throws ClassCastException <B STYLE='color: red;'>IMPORTANT:</B> If the instance is a
407     * {@link TagNode} or {@code TextNode}, rather than a {@link CommentNode}, then (naturally) the
408     * JVM will immediately throw a casting exception.
409     */
410    public CommentNode asCommentNode() { return CommentNode.class.cast(this); }
411
412}