001package Torello.HTML;
002
003import java.util.regex.*;
004
005import Torello.HTML.HelperPackages.TagNode.AttrRegEx;
006
007/**
008 * This occurs whenever a parameter specifies an Inner-Tag
009 * <B STYLE="color: red;">"Key-Value Pair"</B> (which, in this package, are <I>also known
010 * as</I> Attribute-<B STYLE="color: red;">Value</B> Pairs) that contain inappropriate characters
011 * inside the {@code key-String}.
012 *
013 * <BR /><BR /><B CLASS=JDDescLabel>Reg-Ex Rules:</B>
014 * 
015 * <BR />All matching HTML Element Attributes must have attribute-<B STYLE="color: red;">names</B>
016 * (inner-tags) whose nomenclature conforms to this regular-expression: {@code [A-Za-z][\w-]+}.
017 * 
018 * <BR /><BR />All this says is that attribute-<B STYLE="color: red;">names</B> <I>must begin with
019 * an alphabetic character</I>, and then the characters that follow must be "regular-expression"
020 * {@code word-characters '\w'}.
021 * 
022 * <BR /><BR />In a regular-expression, the characters that match a {@code \w} include the letters
023 * {@code A-Z}, the (lower-case) letters {@code a-z}, the digits {@code 0-9}, and the underscore
024 * {@code '_'}.  The minus-sign {@code '-'} may also be used in an
025 * attribute-<B STYLE="color: red;">name</B><I> (it just may not be the first character used in an
026 * attribute-<B STYLE="color: red;">name</B>)</I>.
027 *
028 * <DIV CLASS="EXAMPLE">{@code 
029 *  <IMG SRC="http://example.com/pic.jpg">
030 *  <DIV data-id="this is example data">
031 * }</DIV>
032 * 
033 * <BR />For the above two examples, both the {@code 'SRC'} attribute-name (key-name) and the
034 * {@code 'data-id'} key-<B STYLE="color: red;">name</B> are legitimately named.  No exceptions
035 * would be thrown if a programmer initiated a search using a string to look for an inner-tag that
036 * was named {@code 'src'} nor would there be problems using a string named {@code 'data-id'} to
037 * look for the <B STYLE="color: red;">value</B> of {@code data-id} above.
038 *
039 * <DIV CLASS=EXAMPLE>{@code 
040 * Properties p = new java.util.Properties();
041 * p.put("My Attribute Value", "data 1");
042 * p.put("123Attribute", "data 2");
043 * p.put("SpecialChars!@#$%", "data 3");
044 * TagNode tn = new TagNode("DIV", p, SD.DoubleQuotes, false);
045 * }</DIV>
046 * <BR />An {@code InnerTagKeyException} would be generated <I>for all three cases!</I>  Each of
047 * the above inner-tag <B STYLE="color: red;">key-value pairs</B> have
048 * key-<B STYLE="color: red;">names</B> with illegal characters.
049 * 
050 * <BR /><BR /><B CLASS=JDDescLabel>Specifically:</B>
051 * 
052 * <BR /><BR /><UL CLASS=JDUL>
053 * <LI>Attribute-Value Pair 1: The key-<B STYLE="color: red;">name</B> contains a space.</LI>
054 * <LI>Attribute-Value Pair 2: The key-<B STYLE="color: red;">name</B> begins with a number.</LI>
055 * 
056 * <LI> Attribute-Value Pair 3: The key-<B STYLE="color: red;">name</B> has invalid,
057 *      non-alpha-numeric
058 *      characters!
059 *      </LI>
060 * 
061 * </UL>
062 * 
063 * <BR />If a search were made using an inner-tag (attribute-<B STYLE="color: red;">name</B>)using
064 * a {@code String} that did not meet these criteria, an {@code InnerTagKeyException} would be
065 * thrown.
066 *
067 */
068public class InnerTagKeyException extends IllegalArgumentException
069{
070    /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUIDEX> */
071    public static final long serialVersionUID = 1;
072
073    /** Constructs an {@code InnerTagKeyException} with no detail message. */
074    public InnerTagKeyException()
075    { super(); }
076
077    /**
078     * Constructs an {@code InnerTagKeyException} with the specified detail message.
079     * @param message the detail message.
080     */
081    public InnerTagKeyException(String message)
082    { super(message); }
083
084    /**
085     * Constructs a new exception with the specified detail message and cause.
086     * 
087     * <BR /><BR /><B CLASS=JDDescLabel>NOTE:</B>
088     * 
089     * <BR /><BR />The detail message associated with cause is not automatically incorporated into
090     * this exception's detail message.
091     * 
092     * @param message The detail message (which is saved for later retrieval by the
093     * {@code Throwable.getMessage()} method).
094     * 
095     * @param cause the cause (which is saved for later retrieval by the
096     * {@code Throwable.getCause()} method).  (A null value is permitted, and indicates that the
097     * cause is nonexistent or unknown).
098     */
099    public InnerTagKeyException(String message, Throwable cause)
100    { super(message, cause); }
101
102    /**
103     * Constructs a new exception with the specified cause and a detail message of
104     * {@code (cause==null ? null : cause.toString())} (which typically contains the class and
105     * detail message of cause).
106     * 
107     * This constructor is useful for exceptions that are little more than wrappers for other
108     * throwables.
109     * 
110     * @param cause The cause (which is saved for later retrieval by the
111     * {@code Throwable.getCause()} method).  (A null value is permitted, and indicates that the
112     * cause is nonexistent or unknown.)
113     */
114    public InnerTagKeyException(Throwable cause)
115    { super(cause); }
116
117    /**
118     * This verifies that any Java-{@code String} that is intended to be use as an inner-tag
119     * conforms to the right rules.  If a problem is found, then an {@code InnerTagKeyException} or
120     * {@code NullPointerException} is thrown.
121     * 
122     * @param keys One or many HTML-Inner-Tag to be checked for use as an HTML-Attribute
123     * <B STYLE="color: red;">name</B>
124     * 
125     * @throws InnerTagKeyException If any {@code String} does not match the {@code CHECK_KEY}
126     * Regular-Expression {@code Pattern}.
127     * 
128     * @throws NullPointerException If any of the attributes / inner-tag
129     * <B STYLE="color: red;">keys</B> passed are null.
130     */
131    public static void check(String... keys)
132    {
133        for (String key : keys)
134
135            if (key == null) throw new NullPointerException(
136                "You have passed a null as an Attribute-Name (also known as an " +
137                "'InnerTag-Key Name'), but this is not allowed."
138            );
139
140            else if (! AttrRegEx.ATTRIBUTE_KEY_REGEX.matcher(key).find())
141                throw new InnerTagKeyException
142                    ("Inner-tag key has invalid characters: [" + key + ']');
143    }
144
145    /**
146     * This method is <B>identical</B> to the <B>{@code public static void check(key);}</B>, except
147     * it allows the programmer to add the <B STYLE="color: red;">key-value pair</B> to the 
148     * Exception's error message.  No change to the code is present, except the exception's error
149     * message.
150     * 
151     * @param key Any HTML-Inner-Tag <B STYLE="color: red;">name</B>to be checked for use as an
152     * HTML-Attribute
153     * 
154     * @param value This is the <B STYLE="color: red;">value</B> taken by this
155     * <B STYLE="color: red;">key</B>, it is included for error-logging only, but it is not
156     * checked.
157     * 
158     * @throws InnerTagKeyException If this class does not match the {@code CHECK_KEY} 
159     * Regular-Expression {@code Pattern}, than it throws.
160     */
161    public static void check(String key, String value)
162    {
163        if (key == null) throw new NullPointerException(
164            "You have passed a null as an Attribute-Name (also known as an 'InnerTag-Key Name'), " +
165            "but this is not allowed."
166        );
167
168        if (! AttrRegEx.ATTRIBUTE_KEY_REGEX.matcher(key).find()) 
169            throw new InnerTagKeyException(
170                "The specified inner-tag key has invalid characters: [" + key + "]\n" +
171                "For Key-Value Pair: [" + key + ", " + value + "]"
172            );
173    }
174}