001package Torello.HTML.NodeSearch;
002
003import Torello.HTML.*;
004import Torello.Java.NException;
005
006import java.util.function.Predicate;
007import java.util.Vector;
008
009/**
010 * This class is used internally to do argument validity-checks, and guarantees consistent
011 * exception-message reporting.
012 * 
013 * <BR /><BR />This class is a {@code 'public'} class in this package not because of its
014 * exceptional usability or usefullness, but rather so that it remains visible in case a programmer
015 * wishes to see how the validity-checking mechanisms work in this {@code 'NodeSearch'} package.
016 */
017@Torello.JavaDoc.StaticFunctional
018public class ARGCHECK
019{
020    private ARGCHECK() { }
021
022    /**
023     * Internally Used.  Checks for valid values of {@code 'nth'} to the search methods {@code nth}
024     * and {@code nthFromEnd}.
025     * 
026     * @param nth This is a number identify which search-match to return.  If {@code n = 3}, the
027     * third match shall be returned.  Remember to ensure that a negative number is not passed, nor
028     * a number too large.
029     * 
030     * @param v This should be the html-{@code Vector} on which a search is being performed.
031     * 
032     * <EMBED CLASS='external-html' DATA-FILE-ID=RAWTYPES>
033     * 
034     * @throws NException When a negative value for {@code 'nth'} is passed, or {@code 'nth'} is
035     * greater than the size of the {@code Vector}.
036     */
037    public static int n(int nth, Vector<?> v)
038    {
039        NException.check(nth, v);
040        return nth;
041    }
042
043    /**
044     * Internally Used.  Checks for valid and invalid HTML Token arguments to all search methods.
045     * Calls Java {@code String} method {@code toLowerCase()} on HTML Token and returns it.  All
046     * HTML tokens are stored in lower-case form internally, for quicker comparisons.
047     * 
048     * @param htmlTag Make sure the user is searching for a valid HTMT Element.  If new tags
049     * have been added to the java {@code Collection} (internally represented by 
050     * {@code class java.util.TreeSet}), make sure the check those too.
051     * 
052     * @throws HTMLTokException When an invalid HTML Token Element is passed.
053     * @throws NullPointerException If any of the provided input reference parameters are null.
054     * 
055     * @see HTMLTags
056     */
057    public static String htmlTag(String htmlTag)
058    {
059        HTMLTokException.check(htmlTag);
060        return htmlTag.toLowerCase();
061    }
062
063    /**
064     * Internally Used.  Checks multiple HTML Token arguments to all search methods for validity.
065     * Calls Java {@code String} method {@code String.toLowerCase()} on each HTML Token and returns
066     * the array of tokens - <I>all in lower-case</I>.  All HTML tokens are stored in lower-case
067     * form internally, for quicker comparisons.
068     * 
069     * <BR /><BR /><B CLASS=JDDescLabel>Save Var-Args:</B>
070     * 
071     * <BR />Here, the Var-Args {@code String[]}-Array parameter {@code 'htmlTags'} is not
072     * modified at all.  Upon invocation, this method creates a new instance of the imported
073     * {@code String[]}-Array (using lower-cased {@code String's} stored in place of the
074     * originals).
075     * 
076     * <BR /><BR />All Java-{@code String's} are immutable, and here new lower-case
077     * {@code String's} are being saved to a newly instantiated array.  The original input
078     * parameter will not be modified.
079     * 
080     * @param htmlTags These are a list of html-tags to be checked.
081     * 
082     * @throws HTMLTokException When <I>any</I> invalid HTML Token Element is passed.
083     * @throws NullPointerException If any of the provided input reference parameters are null.
084     * 
085     * @see Torello.HTML.HTMLTags
086     * @see HTMLTokException#check(String[])
087     */
088    public static String[] htmlTags(String... htmlTags)
089    {
090        HTMLTokException.check(htmlTags);
091
092        String[] ret = new String[htmlTags.length];
093
094        for (int i=0; i < htmlTags.length; i++) ret[i] = htmlTags[i].toLowerCase();
095
096        return ret;
097    }
098
099    /**
100     * Internally Used.  Checks validity of inner-tag arguments to search routines.  Returns
101     * lower-case version of the inner-tag.
102     * 
103     * @throws InnerTagKeyException If an inner-tag value is invalid. 
104     * @throws NullPointerException If any of the provided input reference parameters are null.
105     * 
106     * @see InnerTagKeyException#check(String[])
107     */
108    public static String innerTag(String innerTag)
109    {
110        InnerTagKeyException.check(innerTag);
111        return innerTag.toLowerCase();
112    }
113
114    public static final Predicate<String> TRUE = (String innerTagValue) -> true;
115
116    /**
117     * This just keeps a short list of all the instance-objects of {@code class TextComparitor}
118     * that perform the "CSS Class" Checks.  These {@code TextComparitor's}, when used with a 
119     * {@code var-args String[] array} input, should have a finer-grain of exception checking and
120     * error checking performed on their inputs.  Checking to ensure CSS Class {@code String's} 
121     * inside of HTML Elements are <I><B>only checked against valid CSS-Names</I></B> is possible
122     * in this argument-checking class.
123     */
124    protected static final TextComparitor[] CSSTCs =
125    { 
126        TextComparitor.C, TextComparitor.C_OR, TextComparitor.C_AND, 
127        TextComparitor.C_NAND, TextComparitor.C_XOR
128    };
129
130    /**
131     * Internally Used.  Checks validity of the {@code TextComparitor String's}, and the 
132     * {@code TextComparitor}.  Wraps the {@code TextComparitor} and its
133     * {@code String... compareStr} arguments into a Java Lambda {@code Predicate<String>}.
134     * 
135     * @param tc Any valid instance of {@code TextComparitor}
136     * 
137     * @param compareStr A {@code varargs String[] array} of test-{@code String's}.
138     * 
139     * @throws TCCompareStrException This is thrown for invalid search parameters.  Review the
140     * {@code Exception} class itself for what constitutes invalid parameter data.
141     * 
142     * @throws CSSStrException If one of the provided comparison {@code String's} is not a valid
143     * CSS name, <B><I>and</I></B> the {@code TextComparitor} passed is a CSS Class Test
144     * {@code TextComparitor}.
145     * 
146     * @throws NullPointerException If any of the provided input reference parameters are null.
147     * 
148     * @return This returns a {@code String-Predicate} that uses the provided
149     * {@code TextComparitor} and its associated {@code 'compareStr' String[] array} list to test
150     * input {@code String's}.
151     * 
152     * @see TCCompareStrException#check(String[])
153     * @see TextComparitor
154     * @see TextComparitor#test(String, String[])
155     */
156    public static final Predicate<String> TC(TextComparitor tc, String... compareStr)
157    {
158        if (tc == null) throw new NullPointerException(
159            "You have passed a null value to the parameter TextComparitor here, " +
160            "but this is not allowed."
161        );
162
163        TCCompareStrException.check(compareStr);
164
165        for (TextComparitor cssTC : CSSTCs)
166            if (cssTC == tc)
167            { CSSStrException.check(compareStr); break; }
168
169        // String[] cmpStr = compareStr.clone(); // MADNESS, ISN'T IT?
170        return (String innerTagValue) -> tc.test(innerTagValue, compareStr);
171    }
172
173    /**
174     * Internally Used.  Checks validity of the {@code TextComparitor String's}, and the
175     * {@code TextComparitor}.
176     * Wraps the {@code TextComparitor} and its {@code String... compareStr} arguments into a
177     * Java Lambda {@code Predicate<String>}.
178     * 
179     * @param tc Any valid instance of {@code TextComparitor}
180     * 
181     * @param compareStr A {@code varargs String[] array} of test-{@code String's}.
182     * 
183     * @throws TCCompareStrException This is thrown for invalid search parameters.  Review the
184     * {@code Exception} class itself for what constitutes invalid parameter data.
185     * 
186     * @throws CSSStrException If one of the provided {@code compareStr's} is not a valid CSS name,
187     * <B><I>and</I></B> the {@code TextComparitor} passed is a CSS Class Test
188     * {@code TextComparitor}.
189     * 
190     * @throws NullPointerException If any of the provided input reference parameters are null.
191     * 
192     * @return This returns a {@code Predicate<TextNode>} that uses the provided 
193     * {@code TextComparitor} and {@code compareStr's} to test input {@code TextNode's} using the
194     * {@code 'TextNode.str'} field.
195     * 
196     * @see TCCompareStrException#check(String[])
197     * @see TextComparitor
198     * @see TextComparitor#test(String, String[])
199     * @see HTMLNode#str
200     * @see TextNode#str
201     */
202    public static final Predicate<TextNode> TC_TXNP(TextComparitor tc, String... compareStr)
203    {
204        if (tc == null) throw new NullPointerException(
205            "You have passed a null value to the parameter TextComparitor here, " +
206            "but this is not allowed."
207        );
208
209        TCCompareStrException.check(compareStr);
210
211        for (TextComparitor cssTC : CSSTCs)
212            if (cssTC == tc)
213                { CSSStrException.check(compareStr); break; }
214
215        // String[] cmpStr = compareStr.clone(); // MADNESS, ISN'T IT?
216        return (TextNode txn) -> tc.test(txn.str, compareStr);
217    }
218
219
220    /**
221     * Internally Used.  Checks validity of the {@code TextComparitor String's}, and the
222     * {@code TextComparitor}.  Wraps the {@code TextComparitor} and its
223     * {@code String... compareStr} arguments into a Java Lambda {@code Predicate}.
224     * 
225     * @param tc Any valid instance of {@code TextComparitor}
226     * 
227     * @param compareStr A {@code varargs String[] array} of test-{@code String's}.
228     * 
229     * @throws TCCompareStrException This is thrown for invalid search parameters.  Review the
230     * {@code Exception} class itself for what constitutes invalid parameter data.
231     * 
232     * @throws CSSStrException If one of the provided {@code compareStr's} is not a valid CSS name,
233     * <B><I>and</I></B> the {@code TextComparitor} passed is a CSS Class Test
234     * {@code TextComparitor}.
235     * 
236     * @throws NullPointerException If any of the provided input reference parameters are null.
237     * 
238     * @return This returns a {@code Predicate<CommentNode>} that uses the provided
239     * {@code TextComparitor} and {@code compareStr's} to test input {@code CommentNode's} using
240     * the {@code CommentNode.body} field.
241     * 
242     * @see TCCompareStrException#check(String[])
243     * @see TextComparitor
244     * @see TextComparitor#test(String, String[])
245     * @see CommentNode#body
246     */
247    public static final Predicate<CommentNode> TC_CNP(TextComparitor tc, String... compareStr)
248    {
249        if (tc == null) throw new NullPointerException(
250            "You have passed a null value to the parameter TextComparitor here, " +
251            "but this is not allowed."
252        );
253
254        TCCompareStrException.check(compareStr);
255
256        for (TextComparitor cssTC : CSSTCs)
257            if (cssTC == tc)
258                { CSSStrException.check(compareStr); break; }
259
260        // String[] cmpStr = compareStr.clone(); // MADNESS, ISN'T IT?
261        return (CommentNode cn) -> tc.test(cn.body, compareStr);
262    }
263
264    /**
265     * Internally Used.  Checks that a Java Regex {@code Pattern} is not null.  Wraps the reg-ex
266     * {@code Pattern} into a Java Lambda {@code Predicate<String>} Tester Expression.
267     * 
268     * @param p This may be any valid input regular-expression {@code Pattern}.
269     * 
270     * @return This shall return a {@code Predicate<String>} that tests input {@code String's} 
271     * against the regular-expression.
272     * 
273     * @throws NullPointerException If any of the provided input reference parameters are null.
274     */
275    public static final Predicate<String> REGEX(java.util.regex.Pattern p)
276    {
277        if (p == null) throw new NullPointerException(
278            "You have passed a null value to a search-method's regular-expression 'Pattern' " +
279            "parameter, but this is not allowed."
280        );
281
282        return p.asPredicate();
283
284        // return (String innerTagValue) -> p.matcher(innerTagValue).find();
285    }
286
287    /**
288     * Internally Used.  Checks that a Java Regex {@code Pattern} is not null.  Wraps the reg-ex
289     * {@code Pattern} into a Java Lambda {@code Predicate<TextNode>} Tester Expression.
290     * 
291     * @param p This may be any valid input regular-expression {@code Pattern}.
292     * 
293     * @return This shall return a {@code Predicate<TextNode>} that tests input {@code TextNode's}
294     * (using the {@code TextNode.str} - inherited from {@code HTMLNode.str} field) against the
295     * regular-expression.
296     * 
297     * @throws NullPointerException If any of the provided input reference parameters are null.
298     * 
299     * @see HTMLNode#str
300     * @see TextNode#str
301     */
302    public static final Predicate<TextNode> REGEX_TXNP(java.util.regex.Pattern p)
303    {
304        if (p == null) throw new NullPointerException(
305            "You have passed a null value to a search-method's regular-expression 'Pattern' " +
306            "parameter, but this is not allowed."
307        );
308
309        Predicate<String> pred = p.asPredicate();
310
311        return (TextNode txn) -> pred.test(txn.str);
312
313        // return (TextNode txn) -> p.matcher(txn.str).find();
314    }
315
316    /**
317     * Internally Used.  Checks that a Java Regex {@code Pattern} is not null.  Wraps the reg-ex
318     * {@code Pattern} into a Java Lambda {@code Predicate<CommentNode>} Tester Expression.
319     * 
320     * @param p This may be any valid input regular-expression pattern.
321     * 
322     * @return This shall return a {@code CommentNode-Predicate} that tests input
323     * {@code CommentNode's} (using the {@code CommentNode.body} field) against the
324     * regular-expression.
325     * 
326     * @throws NullPointerException If any of the provided input reference parameters are null.
327     * 
328     * @see CommentNode#body
329     */
330    public static final Predicate<CommentNode> REGEX_CNP(java.util.regex.Pattern p)
331    {
332        if (p == null) throw new NullPointerException(
333            "You have passed a null value to a search-method's regular-expression 'Pattern' " +
334            "parameter, but this is not allowed."
335        );
336
337        Predicate<String> pred = p.asPredicate();
338
339        return (CommentNode cn) -> pred.test(cn.body);
340
341        // return (CommentNode cn) -> p.matcher(cn.body).find();
342    }
343
344
345    /**
346     * Internally Used.  Checks that a Java Regex {@code Pattern} is not null.  Wraps the reg-ex
347     * {@code Pattern} into a Java Lambda {@code Predicate<TextNode>} Tester Expression.
348     * 
349     * @param p This may be any valid {@code String-Predicate}
350     * 
351     * @return This shall return a {@code TextNode-Predicate} that "wraps" the input
352     * {@code String-Predicate} and uses the field {@code TextNode.str} (inherited from
353     * {@code HTMLNode.str}) as a value for the wrapped, "original," {@code String-Predicate} test.
354     * 
355     * @throws NullPointerException If any of the provided input reference parameters are null.
356     * 
357     * @see TextNode#str
358     * @see HTMLNode#str
359     */
360    public static final Predicate<TextNode> SP_TO_TXNP(Predicate<String> p)
361    {
362        if (p == null) throw new NullPointerException(
363            "You have passed a null value to a search-method's String-Predicate 'p' parameter, " +
364            "but this is not allowed."
365        );
366
367        return (TextNode txn) -> p.test(txn.str);
368    }
369
370
371    /**
372     * Internally Used.  Checks that a Java Regex {@code Pattern} is not null.  Wraps the reg-ex
373     * {@code Pattern} into a Java Lambda {@code Predicate<CommentNode>} Tester Expression.
374     * 
375     * @param p This may be any valid {@code String-Predicate}
376     * 
377     * @return This shall return a {@code CommentNode-Predicate} that "wraps" the input
378     * {@code String-Predicate} and uses the field {@code CommentNode.body} as a value for the
379     * wrapped, "original," {@code String-Predicate} test.
380     * 
381     * @throws NullPointerException If any of the provided input reference parameters are null.
382     * 
383     * @see CommentNode#body
384     */
385    public static final Predicate<CommentNode> SP_TO_CNP(Predicate<String> p)
386    {
387        if (p == null) throw new NullPointerException(
388            "You have passed a null value to a search-method's String-Predicate 'p' parameter, " +
389            "but this is not allowed."
390        );
391
392        return (CommentNode cn) -> p.test(cn.body);
393    }
394
395    /**
396     * Internally Used.  Checks to ensure that an index-parameter, when use in conjunction with the
397     * {@code class Surrounding} (which is sometimes referred to by the term 'Container') find
398     * methods is properly within the bounds of the HTML page.
399     * 
400     * @param page This may be any valid vectorized-html page or sub-page.  
401     * 
402     * @param index This is expected to be an index into the 'page' parameter-vector.  If this is
403     * not a valid index, then this method shall throw an exception.
404     * 
405     * @return This method returns the exact-value of input parameter 'index'
406     * 
407     * @throws NullPointerException If any of the provided input reference parameters are null.
408     * @throws IndexOutOfBoundsException If the 'index' parameter is not a valid index into the
409     * 'page' parameter, then this exception will be thrown.
410     */
411    public static int index(Vector<? extends HTMLNode> page, int index)
412    {
413        if (index < 0) throw new IndexOutOfBoundsException(
414            "The index you passed [" + index + "] into vectorized-HTML page was negative, " +
415            "this is not allowed here."
416        );
417
418        if (index >= page.size()) throw new IndexOutOfBoundsException(
419            "The index you passed [" + index + "] into vectorized-HTML page was is greater than " +
420            "the vector's size [" + page.size() + "]"
421        );
422
423        return index;
424    }
425}