001package Torello.HTML; 002 003/** 004 * This class is mostly a wrapper for class <CODE>java.lang.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;"><SPAN STYLE="CSS INFO">"</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}