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