1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package Torello.HTML;

/**
 * Represents HTML Comments, and is one of only three HTML Element Classes provided by the Java
 * HTML Library Tool, and also one of the three data-classes that can be generated by the HTML
 * Parser.
 * 
 * <EMBED CLASS='external-html' DATA-FILE-ID=COMMENT_NODE>
 * 
 * <EMBED CLASS='external-html' DATA-FILE-ID=HTML_NODE_SUB_IMG>
 * 
 * @see TagNode
 * @see TextNode
 * @see HTMLNode
 */
@Torello.JavaDoc.JDHeaderBackgroundImg(EmbedTagFileID="HTML_NODE_SUBCLASS")
public final class CommentNode
    extends HTMLNode 
    implements CharSequence, java.io.Serializable, Cloneable, Comparable<CommentNode>
{
    /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */
    public static final long serialVersionUID = 1;

    /**
     * This stores a copy of the body of the comment.  Specifically, (and simply) the java string
     * method {@code body = str.substring(4, str.length() - 3);} is called and stored here.  Yes,
     * this does mean that extra memory / double memory is used to store comments, however the 
     * trade-offs are somewhat high.
     *
     * <BR /><BR /><B><SPAN STYLE="color: red;">TRADEOFFS:</B></SPAN> If the programmer or user
     * ever wishes to perform a search, it becomes obvious that leaving off the beginning and
     * trailing {@code '<!--'} and {@code '-->'} markers when specifying a search provides more
     * easily readable code, and less error prone code.  Thus, when using the
     * {@code CommentNodeFind, Get, Peek, Poll, etc...} methods in the {@code package NodeSearch},
     * a Java String {@code substring(...)} would have to be invoked on every search comparison 
     * loop invocation.  Primarily, keeping {@code class HTMLNode} and it's descendants all
     * immutable is a much higher priority to ensure clean code, it becomes necessary to keep a
     * redundant copy of the body {@code String}.
     */
    public final String body;

    /**
     * This constructor simply makes a call to {@code super(s); } <I>a.k.a.</I>
     * {@code class HTML.HTMLNode}
     * 
     * <BR /><BR />This constructor also checks to ensure that the internal {@code String}-field
     * ({@code public final String str}) contains beginning and ending comment markers:
     * {@code '<!--'} and {@code '-->'}
     *  
     * @throws IllegalArgumentException If the passed string does not start and end with the
     * appropriate HTML comment-markers: {@code <!--} and {@code -->}
     */
    public CommentNode(String s)
    {
        super(s);

        if (! s.startsWith("<!--")) throw new IllegalArgumentException
            ("The passed HTML string does not start with comment marker '<!--'");

        if (! s.endsWith("-->"))    throw new IllegalArgumentException
            ("The passed HTML string does not end with comment marker '-->'");

        body = str.substring(4, str.length() - 3);

        if (body.contains("-->"))   throw new IllegalArgumentException
            ("The passed HTML string has multiple occurrences of substring '-->'");
    }

    /**
     * This method identifies that {@code 'this'} instance of (abstract parent-class)
     * {@link HTMLNode} is, indeed, an instance of sub-class {@code CommentNode}.
     *
     * <BR /><BR /><B CLASS=JDDescLabel>Final Method:</B>
     * 
     * <BR />This method is final, and cannot be modified by sub-classes.
     * 
     * @return This method shall always return {@code TRUE}  It overrides the parent-class
     * {@code HTMLNode} method {@link #isCommentNode()}, which always returns {@code FALSE}.
     */
    @Override
    public final boolean isCommentNode() { return true; }

    /**
     * This method identifies that {@code 'this'} instance of (abstract parent-class)
     * {@link HTMLNode} is, indeed, an instance of sub-class {@code CommentNode}.
     * 
     * <BR /><BR /><B CLASS=JDDescLabel>Final Method:</B>
     * 
     * <BR />This method is final, and cannot be modified by sub-classes.
     * 
     * @return {@code 'this'} reference.  This method can be used inside loops for improving
     * the readability of loop-condition expressions.  See example below:
     * 
     * <DIV CLASS=EXAMPLE>{@code
     * Vector<HTMLNode> fileVec = HTMLPage.getPageTokens(new URL("http://some.url.com"), false);
     * CommentNode c;
     * 
     * // NOTE: The casting to class CommentNode is automatically acheived with this method,
     * //       which can make loops a lot easier to read.  Only a CommentNode instance will have 
     * //       a '.body' field.  Attempting to read a '.body' field from an instance of HTMLNode
     * //       would immediately generate a compile-time error.
     * 
     * for (HTMLNode n : fileVec)
     *     if ((c = myHTMLVector.elementAt(i).ifCommentNode()) != null)
     *         if (c.body.equals("Some Comment Node Text"))
     *             ...
     * }</div>
     * 
     * <BR /><BR />This method-version overrides the parent-class-version, which always returns
     * null.  This method is <I>not overriden by other {@code HTMLNode} sub-classes.</I>
     */
    @Override
    public final CommentNode ifCommentNode() { return this; }

    /**
     * Java's {@code interface Cloneable} requirements.  This instantiates a new
     * {@code CommentNode} with identical {@code String str} and {@code String body} fields.
     * @return A new {@code CommentNode} whose internal fields are identical to this one.
     */
    public CommentNode clone() { return new CommentNode(str); }

    /**
     * Java's {@code interface Comparable<T>} requirements.  This does a very simple comparison
     * using the underlying field {@code final String str} that all {@code HTMLNode's} contain.
     * @param cn Any other {@code CommentNode} to be compared to {@code 'this' CommentNode}
     * @return An integer that fulfils Java's {@code interface Comparable<T> public boolean
     * compareTo(T t)} method requirements.
     */
    public int compareTo(CommentNode cn)
    { return this.body.compareToIgnoreCase(cn.body); }
}