001package Torello.HTML; 002 003/** 004 * Represents HTML Comments, and is one of only three HTML Element Classes provided by the Java 005 * HTML Library Tool, and also one of the three data-classes that can be generated by the HTML 006 * Parser. 007 * 008 * <EMBED CLASS='external-html' DATA-FILE-ID=COMMENT_NODE> 009 * 010 * <EMBED CLASS='external-html' DATA-FILE-ID=HTML_NODE_SUB_IMG> 011 * 012 * @see TagNode 013 * @see TextNode 014 * @see HTMLNode 015 */ 016@Torello.JavaDoc.JDHeaderBackgroundImg(EmbedTagFileID="HTML_NODE_SUBCLASS") 017public final class CommentNode 018 extends HTMLNode 019 implements CharSequence, java.io.Serializable, Cloneable, Comparable<CommentNode> 020{ 021 /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */ 022 public static final long serialVersionUID = 1; 023 024 /** 025 * This stores a copy of the body of the comment. Specifically, (and simply) the java string 026 * method {@code body = str.substring(4, str.length() - 3);} is called and stored here. Yes, 027 * this does mean that extra memory / double memory is used to store comments, however the 028 * trade-offs are somewhat high. 029 * 030 * <BR /><BR /><B CLASS=JDDescLabel>Trade Off:</B> 031 * 032 * <BR />If the programmer or user ever wishes to perform a search, it becomes obvious that 033 * leaving off the beginning and trailing {@code '<!--'} and {@code '-->'} markers when 034 * specifying a search provides more easily readable code, and less error prone code. Thus, 035 * when using the {@code CommentNodeFind, Get, Peek, Poll, etc...} methods in the 036 * {@code package NodeSearch}, a Java String {@code substring(...)} would have to be invoked 037 * on every search comparison loop invocation. Primarily, keeping {@code class HTMLNode} and 038 * it's descendants all immutable is a much higher priority to ensure clean code, it becomes 039 * necessary to keep a redundant copy of the body {@code String}. 040 */ 041 public final String body; 042 043 /** 044 * This constructor simply makes a call to {@code super(s); } <I>a.k.a.</I> 045 * {@code class HTML.HTMLNode} 046 * 047 * <BR /><BR />This constructor also checks to ensure that the internal {@code String}-field 048 * ({@code public final String str}) contains beginning and ending comment markers: 049 * {@code '<!--'} and {@code '-->'} 050 * 051 * @throws IllegalArgumentException If the passed string does not start and end with the 052 * appropriate HTML comment-markers: {@code <!--} and {@code -->} 053 */ 054 public CommentNode(String s) 055 { 056 super(s); 057 058 if (! s.startsWith("<!--")) throw new IllegalArgumentException 059 ("The passed HTML string does not start with comment marker '<!--'"); 060 061 if (! s.endsWith("-->")) throw new IllegalArgumentException 062 ("The passed HTML string does not end with comment marker '-->'"); 063 064 body = str.substring(4, str.length() - 3); 065 066 if (body.contains("-->")) throw new IllegalArgumentException 067 ("The passed HTML string has multiple occurrences of substring '-->'"); 068 } 069 070 /** 071 * This method identifies that {@code 'this'} instance of (abstract parent-class) 072 * {@link HTMLNode} is, indeed, an instance of sub-class {@code CommentNode}. 073 * 074 * <BR /><BR /><B CLASS=JDDescLabel>Final Method:</B> 075 * 076 * <BR />This method is final, and cannot be modified by sub-classes. 077 * 078 * @return This method shall always return {@code TRUE} It overrides the parent-class 079 * {@code HTMLNode} method {@link #isCommentNode()}, which always returns {@code FALSE}. 080 */ 081 @Override 082 public final boolean isCommentNode() { return true; } 083 084 /** 085 * This method identifies that {@code 'this'} instance of (abstract parent-class) 086 * {@link HTMLNode} is, indeed, an instance of sub-class {@code CommentNode}. 087 * 088 * <BR /><BR /><B CLASS=JDDescLabel>Final Method:</B> 089 * 090 * <BR />This method is final, and cannot be modified by sub-classes. 091 * 092 * @return {@code 'this'} reference. This method can be used inside loops for improving 093 * the readability of loop-condition expressions. See example below: 094 * 095 * <DIV CLASS=EXAMPLE>{@code 096 * Vector<HTMLNode> fileVec = HTMLPage.getPageTokens(new URL("http://some.url.com"), false); 097 * CommentNode c; 098 * 099 * // NOTE: The casting to class CommentNode is automatically acheived with this method, 100 * // which can make loops a lot easier to read. Only a CommentNode instance will have 101 * // a '.body' field. Attempting to read a '.body' field from an instance of HTMLNode 102 * // would immediately generate a compile-time error. 103 * 104 * for (HTMLNode n : fileVec) 105 * if ((c = myHTMLVector.elementAt(i).ifCommentNode()) != null) 106 * if (c.body.equals("Some Comment Node Text")) 107 * ... 108 * }</div> 109 * 110 * <BR /><BR />This method-version overrides the parent-class-version, which always returns 111 * null. This method is <I>not overriden by other {@code HTMLNode} sub-classes.</I> 112 */ 113 @Override 114 public final CommentNode ifCommentNode() { return this; } 115 116 /** 117 * Java's {@code interface Cloneable} requirements. This instantiates a new 118 * {@code CommentNode} with identical {@code String str} and {@code String body} fields. 119 * @return A new {@code CommentNode} whose internal fields are identical to this one. 120 */ 121 public CommentNode clone() { return new CommentNode(str); } 122 123 /** 124 * Java's {@code interface Comparable<T>} requirements. This does a very simple comparison 125 * using the underlying field {@code final String str} that all {@code HTMLNode's} contain. 126 * @param cn Any other {@code CommentNode} to be compared to {@code 'this' CommentNode} 127 * @return An integer that fulfils Java's {@code interface Comparable<T> public boolean 128 * compareTo(T t)} method requirements. 129 */ 130 public int compareTo(CommentNode cn) 131 { return this.body.compareToIgnoreCase(cn.body); } 132}