001package Torello.Java;
002
003import java.util.function.Consumer;
004import java.util.function.Predicate;
005import java.util.Vector;
006
007import Torello.JavaDoc.StaticFunctional;
008import Torello.JavaDoc.Excuse;
009
010/**
011 * Similar to class String-Compare, String-Token-Compare also provides an exhaustive suite of
012 * methods that extend the basic Java <CODE>String</CODE> methods <CODE>equals, contains,
013 * startsWith</CODE> and <CODE>endsWith</CODE>, but further allowing a user to specify the 
014 * match-string boundary-characters.
015 * 
016 * <BR /><BR /><EMBED CLASS='external-html' DATA-FILE-ID=STR_TOK_CMPR>
017 */
018@StaticFunctional(Excused={"DEBUG", "DEBUG_LOG"}, Excuses={Excuse.DEBUGGING, Excuse.DEBUGGING})
019public class StrTokCmpr
020{
021    private StrTokCmpr() { }
022
023    /**
024     * Utility field.  You may choose to set this variable to true, and the following
025     * {@code String} commands will print to  an internally stored {@code Consumer<String> DEBUG_LOG}
026     * class that may be set.  This is generally a very minor drain on code-efficiency.  When this
027     * flag is set to {@code FALSE}, a short {@code if-statement evaluation} <I>still occurs even
028     * when the flag is false</I> on each occasion that the string-comparison loops identify and
029     * return a match.  This is very minor performance loss, and does provide quite a lot of help
030     * to those trying to identify difficult to notice problems with partial-{@code String}
031     * comparisons.
032     * 
033     * <BR /><BR /><B CLASS=JDDescLabel>Required Setting:</B>
034     * 
035     * <BR />In order to use this minor Debugging Feature, it is necessary to provide a 
036     * {@code Consumer<String>} to public field {@link #DEBUG_LOG}!  This field is a {@code public}
037     * and {@code static} field, which will be used by any invocation of the methods in this class.
038     * This {@code String}-consumer may do anything you would like it to do with the provided
039     * Debug-{@code String} data.
040     * 
041     * <BR /><BR /><B CLASS=JDDescLabel>String-Format:</B>
042     * 
043     * <BR />The {@code String} that is ultimately sent to the {@code Consumer<String>} you provide
044     * will be formatted, as below, in the following Code-Snippet:
045     * 
046     * <BR /><DIV CLASS=SNIP>{@code
047     * private static void PRNT(String methodName, String srcStr, String compareStr)
048     * { DEBUG_LOG.accept(methodName + "-MATCH[" + srcStr + ", " + compareStr + "] "); }
049     * }</DIV>
050     * 
051     * <BR /><BR />Generally, you would assign a writer that looks like something the Lambda-Target
052     * / Function-Pointer assignment in the snippet below:
053     * 
054     * <BR /><DIV CLASS=SNIP>{@code
055     * StrTokCmpr.DEBUG_LOG = (String logInfoStr) -> System.out.println(logInfoStr);
056     * }</DIV>
057     *
058     * <BR /><BR />Finally, if you are using this field, please note that any of the methods whose
059     * name ends with the phrase "IgnoreCase" <I>will not print to the {@link #DEBUG_LOG}</I>.
060     * This is primarily because these are all <I>single-argument comparisons</I>, and logging
061     * would be of only minor benefit.
062     * 
063     * <BR /><BR />The primary value of a debug-log is the ability to identify whether / when a
064     * particular substring from a list of substrings actually matched.
065     */
066    public static boolean DEBUG = false;
067
068    /**
069     * This object reference <I><B>cannot be null when DEBUG is TRUE</B></I>.  This
070     * {@code StorageWriter} will receive text-notifications every time the string-comparing loops
071     * identify a match.
072     *
073     * <BR /><BR /><B CLASS=JDDescLabel>DEBUG_LOG is not Thread-Safe:</B>
074     * 
075     * <BR />No attempt has been made to ensure that this debugging feature will operate perfectly
076     * in a multi-threaded environment.  The two reasons for this are:
077     *
078     * <BR /><BR /><OL CLASS=JDOL>
079     * <LI> The primary purpose of this LOG is for debugging code, not putting details about
080     *      string-match information into an 'on-line' or production environment.
081     *      </LI>
082     * 
083     * <LI> This is a best-efforts string-comparison package that would sacrifice quite a bit of its
084     *      utility if it were expected to maintain multiple instances of this class just to have
085     *      {@code StrCmpr} debug operations work in multiple-threads.  Code readability necessitates
086     *      keeping this a class with only <B><I>static methods.</I></B>
087     *      </LI>
088     * 
089     * <LI> Two threads making calls to this {@code class StrCmpr} might see log-writes that, sadly,
090     *      look like they 'interlaced' (crashed), but even when this occasions, reading the log
091     *      wouldn't be that difficult anyway.
092     *      </LI>
093     * </OL>
094     */
095    public static Consumer<String> DEBUG_LOG = null;
096
097    private static void PRNT(String methodName, String srcStr, String token)
098    { DEBUG_LOG.accept(methodName + srcStr + ", " + token + "] "); }
099
100    /**
101     * This performs the internal AND.  It expects a comparison {@code Predicate} in order for the
102     * comparison to work.
103     * @param methodName If printing-debug information is expected, by the DEBUG global-variable,
104     * this {@code String} is used.
105     * @param srcStr This is the same source-string parameter from all the methods in this class.
106     * @param tokens This is the same var-args string array from all the methods in this class.
107     * @param pred This is the comparison {@code Predicate} provided by the methods in this class
108     * that call this method.
109     * @return The AND of these {@code String's}, using the provided {@code Predicate}.
110     * @throws StrCmprException This exception shall throw if there are any invalid
111     * {@code String's} in the compare-string parameter array.
112     * <BR /><BR /><SPAN STYLE="color: red;"><B>IMPORTANT NOTE:</SPAN></B> The conditions that
113     * would cause this exception to throw should remind the reader that <I><B>each and every
114     * method here</I></B> will throw exception 'StrCmprException' if invalid input has been
115     * passed to the "Compare String" Variable-Arguments {@code String...} Parameter.
116     */
117    protected static boolean AND
118        (String methodName, String srcStr, String[] tokens, Predicate<String> pred)
119    {
120        StrCmprException.check(tokens);
121
122        for (String cmp: tokens)
123
124            if (! pred.test(cmp))
125            {
126                if (DEBUG) PRNT(methodName + "-MATCHFAIL", srcStr, cmp);
127                return false;
128            }
129
130        return true;
131    }
132
133    /**
134     * This performs the internal NAND.  It expects a comparison {@code Predicate} in order for the
135     * comparison to work.
136     * @param methodName If printing-debug information is expected, by the DEBUG global-variable,
137     * this {@code String} is used.
138     * @param srcStr This is the same source-string parameter from all the methods in this class.
139     * @param tokens This is the same var-args string array from all the methods in this class.
140     * @param pred This is the comparison {@code Predicate} provided by the methods in this class
141     * that call this method.
142     * @return The NAND of these {@code String's}, using the provided {@code Predicate}.
143     * @throws StrCmprException This exception shall throw if there are any invalid
144     * {@code String's} in the compare-string parameter array.
145     * <BR /><BR /><SPAN STYLE="color: red;"><B>IMPORTANT NOTE:</SPAN></B> The conditions that
146     * would cause this exception to throw should remind the reader that <I><B>each and every
147     * method here</I></B> will throw exception 'StrCmprException' if invalid input has been passed
148     * to the "Compare String" Variable-Arguments {@code String...} Parameter.
149     */
150    protected static boolean NAND
151        (String methodName, String srcStr, String[] tokens, Predicate<String> pred)
152    {
153        StrCmprException.check(tokens); 
154
155        for (String cmp: tokens) 
156
157            if (pred.test(cmp))
158            {
159                if (DEBUG) PRNT(methodName + "-MATCH", srcStr, cmp);
160                return false;
161            }
162
163        return true;
164    }
165
166    /**
167     * This performs the internal OR.  It expects a comparison {@code Predicate} in order for the
168     * comparison to work.
169     * @param methodName If printing-debug information is expected, by the DEBUG global-variable,
170     * this {@code String} is used.
171     * @param srcStr This is the same source-string parameter from all the methods in this class.
172     * @param tokens This is the same var-args string array from all the methods in this class.
173     * @param pred This is the comparison {@code Predicate} provided by the methods in this class
174     * that call this method.
175     * @return The OR of these {@code String's}, using the provided {@code Predicate}.
176     * @throws StrCmprException This exception shall throw if there are any invalid
177     * {@code String's} in the compare-string parameter array.
178     * <BR /><BR /><SPAN STYLE="color: red;"><B>IMPORTANT NOTE:</SPAN></B> The conditions that
179     * would cause this exception to throw should remind the reader that <I><B>each and every
180     * method here</I></B> will throw exception 'StrCmprException' if invalid input has been passed
181     * to the "Compare String" Variable-Arguments {@code String...} Parameter.
182     */
183    protected static boolean OR
184        (String methodName, String srcStr, String[] tokens, Predicate<String> pred)
185    {
186        StrCmprException.check(tokens);
187
188        for (String cmp: tokens)
189
190            if (pred.test(cmp))
191            {
192                if (DEBUG) PRNT(methodName + "-MATCH", srcStr, cmp);
193                return true;
194            }
195
196        return false;
197    }
198
199    /**
200     * This performs the internal XOR.  It expects a comparison {@code Predicate} in order for the
201     * comparison to work.
202     * @param methodName If printing-debug information is expected, by the DEBUG global-variable,
203     * this {@code String} is used.
204     * @param srcStr This is the same source-string parameter from all the methods in this class.
205     * @param tokens This is the same var-args string array from all the methods in this class.
206     * @param pred This is the comparison {@code Predicate} provided by the methods in this class
207     * that call this method.
208     * @return The XOR of these {@code String's}, using the provided {@code Predicate}.
209     * @throws StrCmprException This exception shall throw if there are any invalid
210     * {@code String's} in the compare-string parameter array.
211     * <BR /><BR /><SPAN STYLE="color: red;"><B>IMPORTANT NOTE:</SPAN></B> The conditions that
212     * would cause this exception to throw should remind the reader that <I><B>each and every
213     * method here</I></B> will throw exception 'StrCmprException' if invalid
214     * input has been passed to the "Compare String" Variable-Arguments {@code String...}
215     * Parameter.
216     */
217    protected static boolean XOR
218        (String methodName, String srcStr, String[] tokens, Predicate<String> pred)
219    {
220        StrCmprException.check(tokens); 
221
222        int count=0;
223
224        for (String cmp: tokens)
225
226            if (pred.test(cmp))
227                if (++count > 1)
228                {
229                    if (DEBUG) PRNT(methodName + "-MATCH", srcStr, cmp);
230                    return false;
231                }
232
233        return count == 1;
234    }
235
236
237
238
239
240
241
242
243
244
245
246    // ********************************************************************************************
247    // ********************************************************************************************
248    // ********************************************************************************************
249    // ********************************************************************************************
250    // ********************************************************************************************
251    // ********************************************************************************************
252    // StrCmpr Main Section #1
253    // ********************************************************************************************
254    // ********************************************************************************************
255    // ********************************************************************************************
256    // ********************************************************************************************
257    // ********************************************************************************************
258
259
260    
261    // ********************************************************************************************
262    // ********************************************************************************************
263    // CONTAINS
264    // ********************************************************************************************
265    // ********************************************************************************************
266
267
268    /**
269     * <EMBED CLASS=defs DATA-DESC='contains at least one' DATA-CI='is'>
270     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
271     * @param srcStr Any non-null instance of {@code java.lang.String}
272     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
273     * <EMBED CLASS='external-html' DATA-FILE-ID='CNNODELIM'>
274     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
275     * @see #CONTAINS(boolean, byte, String, String[])
276     */
277    public static boolean containsOR(String srcStr, String... tokens)
278    { return CONTAINS(false, OR, srcStr, tokens); }
279
280    /**
281     * <EMBED CLASS=defs DATA-DESC='contains every one' DATA-CI='is'>
282     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
283     * @param srcStr Any non-null instance of {@code java.lang.String}
284     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
285     * <EMBED CLASS='external-html' DATA-FILE-ID='CNNODELIM'>
286     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
287     * @see #CONTAINS(boolean, byte, String, String[])
288     */
289    public static boolean containsAND(String srcStr, String... tokens)
290    { return CONTAINS(false, AND, srcStr, tokens); }
291
292    /**
293     * <EMBED CLASS=defs DATA-DESC='contains exactly one' DATA-CI='is'>
294     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
295     * @param srcStr Any non-null instance of {@code java.lang.String}
296     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
297     * <EMBED CLASS='external-html' DATA-FILE-ID='CNNODELIM'>
298     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
299     * @see #CONTAINS(boolean, byte, String, String[])
300     */
301    public static boolean containsXOR(String srcStr, String... tokens)
302    { return CONTAINS(false, XOR, srcStr, tokens); }
303
304    /**
305     * <EMBED CLASS=defs DATA-DESC='does not contain any' DATA-CI='is'>
306     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
307     * @param srcStr Any non-null instance of {@code java.lang.String}
308     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
309     * <EMBED CLASS='external-html' DATA-FILE-ID='CNNODELIM'>
310     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
311     * @see #CONTAINS(boolean, byte, String, String[])
312     */
313    public static boolean containsNAND(String srcStr, String... tokens)
314    { return CONTAINS(false, NAND, srcStr, tokens); }
315
316    /**
317     * <EMBED CLASS=defs DATA-DESC='contains at least one' DATA-CI='is not'>
318     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
319     * @param srcStr Any non-null instance of {@code java.lang.String}
320     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
321     * <EMBED CLASS='external-html' DATA-FILE-ID='CNNODELIM'>
322     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
323     * @see #CONTAINS(boolean, byte, String, String[])
324     */
325    public static boolean containsOR_CI(String srcStr, String... tokens)
326    { return CONTAINS(true, OR, srcStr, tokens); }
327
328    /**
329     * <EMBED CLASS=defs DATA-DESC='contains every one' DATA-CI='is not'>
330     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
331     * @param srcStr Any non-null instance of {@code java.lang.String}
332     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
333     * <EMBED CLASS='external-html' DATA-FILE-ID='CNNODELIM'>
334     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
335     * @see #CONTAINS(boolean, byte, String, String[])
336     */
337    public static boolean containsAND_CI(String srcStr, String... tokens)
338    { return CONTAINS(true, AND, srcStr, tokens); }
339
340    /**
341     * <EMBED CLASS=defs DATA-DESC='contains exactly one' DATA-CI='is not'>
342     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
343     * @param srcStr Any non-null instance of {@code java.lang.String}
344     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
345     * <EMBED CLASS='external-html' DATA-FILE-ID='CNNODELIM'>
346     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
347     * @see #CONTAINS(boolean, byte, String, String[])
348     */
349    public static boolean containsXOR_CI(String srcStr, String... tokens)
350    { return CONTAINS(true, XOR, srcStr, tokens); }
351
352    /**
353     * <EMBED CLASS=defs DATA-DESC='does not contain any' DATA-CI='is not'>
354     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
355     * @param srcStr Any non-null instance of {@code java.lang.String}
356     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
357     * <EMBED CLASS='external-html' DATA-FILE-ID='CNNODELIM'>
358     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
359     * @see #CONTAINS(boolean, byte, String, String[])
360     */
361    public static boolean containsNAND_CI(String srcStr, String... tokens)
362    { return CONTAINS(true, NAND, srcStr, tokens); }
363
364
365    // ********************************************************************************************
366    // ********************************************************************************************
367    // STARTS-WITH, ENDS-WITH
368    // ********************************************************************************************
369    // ********************************************************************************************
370
371
372    /**
373     * <EMBED CLASS=defs DATA-DESC='ends with exactly one' DATA-CI='is'>
374     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
375     * @param srcStr Any non-null instance of {@code java.lang.String}
376     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
377     * <EMBED CLASS='external-html' DATA-FILE-ID='EWNODELIM'>
378     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
379     * @see #XOR(String, String, String[], Predicate)
380     * @see #endsWith(String, LV, String)
381     */
382    public static boolean endsWithXOR(String srcStr, String... tokens)
383    { return XOR("endsWithXOR", srcStr, tokens, cmp -> endsWith(srcStr, new LV(srcStr, 0, -1), cmp)); }
384
385    /**
386     * <EMBED CLASS=defs DATA-DESC='does not end with any' DATA-CI='is'>
387     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
388     * @param srcStr Any non-null instance of {@code java.lang.String}
389     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
390     * <EMBED CLASS='external-html' DATA-FILE-ID='EWNODELIM'>
391     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
392     * @see #NAND(String, String, String[], Predicate)
393     * @see #endsWith(String, LV, String)
394     */
395    public static boolean endsWithNAND(String srcStr, String... tokens)
396    { return NAND("endsWithNAND", srcStr, tokens, cmp -> endsWith(srcStr, new LV(srcStr, 0, -1), cmp)); }
397
398    /**
399     * <EMBED CLASS=defs DATA-DESC='starts with exactly one' DATA-CI='is'>
400     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
401     * @param srcStr Any non-null instance of {@code java.lang.String}
402     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
403     * <EMBED CLASS='external-html' DATA-FILE-ID='SWNODELIM'>
404     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
405     * @see #XOR(String, String, String[], Predicate)
406     * @see #startsWith(String, LV, String)
407     */
408    public static boolean startsWithXOR(String srcStr, String... tokens)
409    { return XOR("startsWithXOR", srcStr, tokens, cmp -> startsWith(srcStr, new LV(srcStr, 0, -1), cmp)); }
410
411    /**
412     * <EMBED CLASS=defs DATA-DESC='does not start with any' DATA-CI='is'>
413     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
414     * @param srcStr Any non-null instance of {@code java.lang.String}
415     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
416     * <EMBED CLASS='external-html' DATA-FILE-ID='SWNODELIM'>
417     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
418     * @see #NAND(String, String, String[], Predicate)
419     * @see #startsWith(String, LV, String)
420     */
421    public static boolean startsWithNAND(String srcStr, String... tokens)
422    { return NAND("startsWithNAND", srcStr, tokens, cmp -> startsWith(srcStr, new LV(srcStr, 0, -1), cmp)); }
423
424
425    // ********************************************************************************************
426    // ********************************************************************************************
427    // STARTS-WITH, ENDS-WITH - CASE INSENSITIVE
428    // ********************************************************************************************
429    // ********************************************************************************************
430
431
432    /**
433     * <EMBED CLASS=defs DATA-DESC='ends with exactly one' DATA-CI='is not'>
434     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
435     * @param srcStr Any non-null instance of {@code java.lang.String}
436     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
437     * <EMBED CLASS='external-html' DATA-FILE-ID='EWNODELIM'>
438     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
439     * @see #endsWithIgnoreCase(String, String)
440     * @see #XOR(String, String, String[], Predicate)
441     */
442    public static boolean endsWithXOR_CI(String srcStr, String... tokens)
443    { return XOR("endsWithXOR_CI", srcStr, tokens, cmp -> endsWithIgnoreCase(srcStr, cmp)); }
444
445    /**
446     * <EMBED CLASS=defs DATA-DESC='does not end with any' DATA-CI='is not'>
447     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
448     * @param srcStr Any non-null instance of {@code java.lang.String}
449     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
450     * <EMBED CLASS='external-html' DATA-FILE-ID='EWNODELIM'>
451     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
452     * @see #endsWithIgnoreCase(String, String)
453     * @see #NAND(String, String, String[], Predicate)
454     */
455    public static boolean endsWithNAND_CI(String srcStr, String... tokens)
456    { return NAND("endsWithNAND_CI", srcStr, tokens, cmp -> endsWithIgnoreCase(srcStr, cmp)); }
457
458    /**
459     * <EMBED CLASS=defs DATA-DESC='starts with exactly one' DATA-CI='is not'>
460     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
461     * @param srcStr Any non-null instance of {@code java.lang.String}
462     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
463     * <EMBED CLASS='external-html' DATA-FILE-ID='SWNODELIM'>
464     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
465     * @see #startsWithIgnoreCase(String, String)
466     * @see #XOR(String, String, String[], Predicate)
467     */
468    public static boolean startsWithXOR_CI(String srcStr, String... tokens)
469    { return XOR("startsWithXOR_CI", srcStr, tokens, cmp -> startsWithIgnoreCase(srcStr, cmp)); }
470
471    /**
472     * <EMBED CLASS=defs DATA-DESC='does not start with any' DATA-CI='is not'>
473     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
474     * @param srcStr Any non-null instance of {@code java.lang.String}
475     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
476     * <EMBED CLASS='external-html' DATA-FILE-ID='SWNODELIM'>
477     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
478     * @see #startsWithIgnoreCase(String, String)
479     * @see #NAND(String, String, String[], Predicate)
480     */
481    public static boolean startsWithNAND_CI(String srcStr, String... tokens)
482    { return NAND("startsWithNAND_CI", srcStr, tokens, cmp -> startsWithIgnoreCase(srcStr, cmp)); }
483
484    // ********************************************************************************************
485    // Three Standard Java Methods, Added Token Checking
486    // ********************************************************************************************
487
488    /**
489     * <EMBED CLASS=defs DATA-FUNC='starts with' DATA-CI='is'>
490     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_1C>
491     * @param srcStr Any non-null instance of {@code java.lang.String}
492     * @param token The {@code String} used in the comparison against {@code 'srcStr'}
493     * <EMBED CLASS='external-html' DATA-FILE-ID='SWNODELIM'>
494     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_1C>
495     */
496    public static boolean startsWith(String srcStr, String token)
497    {
498        return  srcStr.startsWith(token)
499                && (    (token.length() == srcStr.length())
500                    ||  Character.isWhitespace(srcStr.charAt(token.length())));
501    }
502
503    /**
504     * <EMBED CLASS=defs DATA-FUNC='ends with' DATA-CI='is'>
505     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_1C>
506     * @param srcStr Any non-null instance of {@code java.lang.String}
507     * @param token The {@code String} used in the comparison against {@code 'srcStr'}
508     * <EMBED CLASS='external-html' DATA-FILE-ID='EWNODELIM'>
509     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_1C>
510     */
511    public static boolean endsWith(String srcStr, String token)
512    {
513        return  srcStr.endsWith(token)
514                &&  (   (token.length() == srcStr.length())
515                    ||  (Character.isWhitespace(srcStr.charAt(srcStr.length() - token.length() - 1))));
516    }
517
518    /**
519     * <EMBED CLASS=defs DATA-FUNC='contains' DATA-CI='is'>
520     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_1C>
521     * @param srcStr Any non-null instance of {@code java.lang.String}
522     * @param token The {@code String} used in the comparison against {@code 'srcStr'}
523     * <EMBED CLASS='external-html' DATA-FILE-ID='CNNODELIM'>
524     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_1C>
525     */
526    public static boolean contains(String srcStr, String token)
527    { 
528        int tokenLen    = token.length();
529        int loopLen     = srcStr.length() - tokenLen;
530
531        for (int i=0; i <= loopLen; i++)
532
533            if (    srcStr.regionMatches(i, token, 0, tokenLen)
534                &&  (   (i == 0)
535                    ||  Character.isWhitespace(srcStr.charAt(i-1)))
536                &&  (   ((i + tokenLen) == srcStr.length())
537                    ||  Character.isWhitespace(srcStr.charAt(i + tokenLen)))
538                )
539                return true;
540
541        return false;
542    }
543
544
545    // ********************************************************************************************
546    // ********************************************************************************************
547    // IGNORE-CASE METHODS
548    // ********************************************************************************************
549    // ********************************************************************************************
550
551
552    /**
553     * <EMBED CLASS=defs DATA-FUNC='starts with' DATA-CI='is not'>
554     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_1C>
555     * @param srcStr Any non-null instance of {@code java.lang.String}
556     * @param token The {@code String} used in the comparison against {@code 'srcStr'}
557     * <EMBED CLASS='external-html' DATA-FILE-ID='SWNODELIM'>
558     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_1C>
559     */
560    public static boolean startsWithIgnoreCase(String srcStr, String token)
561    {
562        return  srcStr.regionMatches(true, 0, token, 0, token.length())
563                && (    (token.length() == srcStr.length())
564                    ||  Character.isWhitespace(srcStr.charAt(token.length())));
565    }
566
567    /**
568     * <EMBED CLASS=defs DATA-FUNC='ends with' DATA-CI='is not'>
569     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_1C>
570     * @param srcStr Any non-null instance of {@code java.lang.String}
571     * @param token The {@code String} used in the comparison against {@code 'srcStr'}
572     * <EMBED CLASS='external-html' DATA-FILE-ID='EWNODELIM'>
573     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_1C>
574     */
575    public static boolean endsWithIgnoreCase(String srcStr, String token)
576    {
577        int tokenLen = token.length();
578        int startPos = srcStr.length() - tokenLen;
579
580        return  srcStr.regionMatches(true, startPos, token, 0, tokenLen)
581                &&  (   (tokenLen == srcStr.length())
582                    ||  (Character.isWhitespace(srcStr.charAt(startPos - 1))));
583    }
584
585    /**
586     * <EMBED CLASS=defs DATA-FUNC='contains' DATA-CI='is not'>
587     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_1C>
588     * @param srcStr Any non-null instance of {@code java.lang.String}
589     * @param token The {@code String} used in the comparison against {@code 'srcStr'}
590     * <EMBED CLASS='external-html' DATA-FILE-ID='CNNODELIM'>
591     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_1C>
592     * @see #containsIgnoreCase(String, LV, String)
593     */
594    public static boolean containsIgnoreCase(String srcStr, String token)
595    { return containsIgnoreCase(srcStr, new LV(srcStr, 0, srcStr.length()), token); }
596
597
598
599
600
601
602
603
604
605
606
607    // ********************************************************************************************
608    // ********************************************************************************************
609    // ********************************************************************************************
610    // ********************************************************************************************
611    // ********************************************************************************************
612    // StrCmpr Main Section
613    // ********************************************************************************************
614    // ********************************************************************************************
615    // ********************************************************************************************
616    // ********************************************************************************************
617    // ********************************************************************************************
618
619
620
621    // ********************************************************************************************
622    // ********************************************************************************************
623    // CONTAINS
624    // ********************************************************************************************
625    // ********************************************************************************************
626
627
628    /**
629     * <EMBED CLASS=defs DATA-DESC='contains at least one' DATA-CI='is'>
630     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
631     * @param srcStr Any non-null instance of {@code java.lang.String}
632     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
633     * <EMBED CLASS='external-html' DATA-FILE-ID='CNNODELIM'>
634     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
635     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
636     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
637     * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
638     * @see #CONTAINS(boolean, byte, LV, String, String[])
639     */
640    public static boolean containsOR(String srcStr, int sPos, int ePos, String... tokens)
641    {
642        LV l = new LV(srcStr, sPos, ePos);
643        return CONTAINS(false, OR, l, srcStr, tokens);
644    }
645
646    /**
647     * <EMBED CLASS=defs DATA-DESC='contains every one' DATA-CI='is'>
648     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
649     * @param srcStr Any non-null instance of {@code java.lang.String}
650     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
651     * <EMBED CLASS='external-html' DATA-FILE-ID='CNNODELIM'>
652     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
653     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
654     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
655     * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
656     * @see #CONTAINS(boolean, byte, LV, String, String[])
657     */
658    public static boolean containsAND(String srcStr, int sPos, int ePos, String... tokens)
659    {
660        LV l = new LV(srcStr, sPos, ePos);
661        return CONTAINS(false, AND, l, srcStr, tokens);
662    }
663
664    /**
665     * <EMBED CLASS=defs DATA-DESC='contains exactly one' DATA-CI='is'>
666     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
667     * @param srcStr Any non-null instance of {@code java.lang.String}
668     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
669     * <EMBED CLASS='external-html' DATA-FILE-ID='CNNODELIM'>
670     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
671     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
672     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
673     * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
674     * @see #CONTAINS(boolean, byte, LV, String, String[])
675     */
676    public static boolean containsXOR(String srcStr, int sPos, int ePos, String... tokens)
677    {
678        LV l = new LV(srcStr, sPos, ePos);
679        return CONTAINS(false, XOR, l, srcStr, tokens);
680    }
681
682    /**
683     * <EMBED CLASS=defs DATA-DESC='does not contain any' DATA-CI='is'>
684     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
685     * @param srcStr Any non-null instance of {@code java.lang.String}
686     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
687     * <EMBED CLASS='external-html' DATA-FILE-ID='CNNODELIM'>
688     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
689     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
690     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
691     * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
692     * @see #CONTAINS(boolean, byte, LV, String, String[])
693     */
694    public static boolean containsNAND(String srcStr, int sPos, int ePos, String... tokens)
695    {
696        LV l = new LV(srcStr, sPos, ePos);
697        return CONTAINS(false, NAND, l, srcStr, tokens);
698    }
699
700    /**
701     * <EMBED CLASS=defs DATA-DESC='contains at least one' DATA-CI='is not'>
702     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
703     * @param srcStr Any non-null instance of {@code java.lang.String}
704     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
705     * <EMBED CLASS='external-html' DATA-FILE-ID='CNNODELIM'>
706     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
707     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
708     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
709     * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
710     * @see #CONTAINS(boolean, byte, LV, String, String[])
711     */
712    public static boolean containsOR_CI(String srcStr, int sPos, int ePos, String... tokens)
713    {
714        LV l = new LV(srcStr, sPos, ePos);
715        return CONTAINS(true, OR, l, srcStr, tokens);
716    }
717
718    /**
719     * <EMBED CLASS=defs DATA-DESC='contains every one' DATA-CI='is not'>
720     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
721     * @param srcStr Any non-null instance of {@code java.lang.String}
722     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
723     * <EMBED CLASS='external-html' DATA-FILE-ID='CNNODELIM'>
724     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
725     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
726     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
727     * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
728     * @see #CONTAINS(boolean, byte, LV, String, String[])
729     */
730    public static boolean containsAND_CI(String srcStr, int sPos, int ePos, String... tokens)
731    {
732        LV l = new LV(srcStr, sPos, ePos);
733        return CONTAINS(true, AND, l, srcStr, tokens);
734    }
735
736    /**
737     * <EMBED CLASS=defs DATA-DESC='contains exactly one' DATA-CI='is not'>
738     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
739     * @param srcStr Any non-null instance of {@code java.lang.String}
740     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
741     * <EMBED CLASS='external-html' DATA-FILE-ID='CNNODELIM'>
742     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
743     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
744     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
745     * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
746     * @see #CONTAINS(boolean, byte, LV, String, String[])
747     */
748    public static boolean containsXOR_CI(String srcStr, int sPos, int ePos, String... tokens)
749    {
750        LV l = new LV(srcStr, sPos, ePos);
751        return CONTAINS(true, XOR, l, srcStr, tokens);
752    }
753
754    /**
755     * <EMBED CLASS=defs DATA-DESC='does not contain any' DATA-CI='is not'>
756     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
757     * @param srcStr Any non-null instance of {@code java.lang.String}
758     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
759     * <EMBED CLASS='external-html' DATA-FILE-ID='CNNODELIM'>
760     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
761     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
762     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
763     * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
764     * @see #CONTAINS(boolean, byte, LV, String, String[])
765     */
766    public static boolean containsNAND_CI(String srcStr, int sPos, int ePos, String... tokens)
767    {
768        LV l = new LV(srcStr, sPos, ePos);
769        return CONTAINS(true, NAND, l, srcStr, tokens);
770    }
771
772
773    // ********************************************************************************************
774    // ********************************************************************************************
775    // STARTS-WITH, ENDS-WITH
776    // ********************************************************************************************
777    // ********************************************************************************************
778
779
780    /**
781     * <EMBED CLASS=defs DATA-DESC='ends with exactly one' DATA-CI='is'>
782     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
783     * @param srcStr Any non-null instance of {@code java.lang.String}
784     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
785     * <EMBED CLASS='external-html' DATA-FILE-ID='EWNODELIM'>
786     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
787     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
788     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
789     * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
790     * @see #endsWith(String, LV, String)
791     * @see #XOR(String, String, String[], Predicate)
792     */
793    public static boolean endsWithXOR(String srcStr, int sPos, int ePos, String... tokens)
794    {
795        LV l = new LV(srcStr, sPos, ePos);
796        return XOR("endsWithXOR", srcStr, tokens, cmp -> endsWith(srcStr, l, cmp));
797    }
798
799    /**
800     * <EMBED CLASS=defs DATA-DESC='does not end with any' DATA-CI='is'>
801     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
802     * @param srcStr Any non-null instance of {@code java.lang.String}
803     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
804     * <EMBED CLASS='external-html' DATA-FILE-ID='EWNODELIM'>
805     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
806     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
807     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
808     * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
809     * @see #endsWith(String, LV, String)
810     * @see #NAND(String, String, String[], Predicate)
811     */
812    public static boolean endsWithNAND(String srcStr, int sPos, int ePos, String... tokens)
813    {
814        LV l = new LV(srcStr, sPos, ePos);
815        return NAND("endsWithNAND", srcStr, tokens, cmp -> endsWith(srcStr, l, cmp));
816    }
817
818    /**
819     * <EMBED CLASS=defs DATA-DESC='starts with exactly one' DATA-CI='is'>
820     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
821     * @param srcStr Any non-null instance of {@code java.lang.String}
822     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
823     * <EMBED CLASS='external-html' DATA-FILE-ID='SWNODELIM'>
824     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
825     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
826     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
827     * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
828     * @see #startsWith(String, LV, String)
829     * @see #XOR(String, String, String[], Predicate)
830     */
831    public static boolean startsWithXOR(String srcStr, int sPos, int ePos, String... tokens)
832    {
833        LV l = new LV(srcStr, sPos, ePos);
834        return XOR("startsWithXOR", srcStr, tokens, cmp -> startsWith(srcStr, l, cmp));
835    }
836
837    /**
838     * <EMBED CLASS=defs DATA-DESC='does not start with any' DATA-CI='is'>
839     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
840     * @param srcStr Any non-null instance of {@code java.lang.String}
841     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
842     * <EMBED CLASS='external-html' DATA-FILE-ID='SWNODELIM'>
843     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
844     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
845     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
846     * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
847     * @see #startsWith(String, LV, String)
848     * @see #NAND(String, String, String[], Predicate)
849     */
850    public static boolean startsWithNAND(String srcStr, int sPos, int ePos, String... tokens)
851    {
852        LV l = new LV(srcStr, sPos, ePos);
853        return NAND("startsWithNAND", srcStr, tokens, cmp -> startsWith(srcStr, l, cmp));
854    }
855
856
857    // ********************************************************************************************
858    // ********************************************************************************************
859    // STARTS-WITH, ENDS-WITH - CASE INSENSITIVE
860    // ********************************************************************************************
861    // ********************************************************************************************
862
863
864    /**
865     * <EMBED CLASS=defs DATA-DESC='ends with exactly one' DATA-CI='is not'>
866     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
867     * @param srcStr Any non-null instance of {@code java.lang.String}
868     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
869     * <EMBED CLASS='external-html' DATA-FILE-ID='EWNODELIM'>
870     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
871     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
872     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
873     * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
874     * @see #endsWithIgnoreCase(String, LV, String)
875     * @see #XOR(String, String, String[], Predicate)
876     */
877    public static boolean endsWithXOR_CI(String srcStr, int sPos, int ePos, String... tokens)
878    {
879        LV l = new LV(srcStr, sPos, ePos);
880        return XOR("endsWithXOR_CI", srcStr, tokens, cmp -> endsWithIgnoreCase(srcStr, l, cmp));
881    }
882
883    /**
884     * <EMBED CLASS=defs DATA-DESC='does not end with any' DATA-CI='is not'>
885     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
886     * @param srcStr Any non-null instance of {@code java.lang.String}
887     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
888     * <EMBED CLASS='external-html' DATA-FILE-ID='EWNODELIM'>
889     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
890     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
891     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
892     * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
893     * @see #endsWithIgnoreCase(String, LV, String)
894     * @see #NAND(String, String, String[], Predicate)
895     */
896    public static boolean endsWithNAND_CI(String srcStr, int sPos, int ePos, String... tokens)
897    {
898        LV l = new LV(srcStr, sPos, ePos);
899        return NAND("endsWithNAND_CI", srcStr, tokens, cmp -> endsWithIgnoreCase(srcStr, l, cmp));
900    }
901
902    /**
903     * <EMBED CLASS=defs DATA-DESC='starts with exactly one' DATA-CI='is not'>
904     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
905     * @param srcStr Any non-null instance of {@code java.lang.String}
906     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
907     * <EMBED CLASS='external-html' DATA-FILE-ID='SWNODELIM'>
908     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
909     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
910     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
911     * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
912     * @see #startsWithIgnoreCase(String, LV, String)
913     * @see #XOR(String, String, String[], Predicate)
914     */
915    public static boolean startsWithXOR_CI(String srcStr, int sPos, int ePos, String... tokens)
916    {
917        LV l = new LV(srcStr, sPos, ePos);
918        return XOR
919            ("startsWithXOR_CI", srcStr, tokens, cmp -> startsWithIgnoreCase(srcStr, l, cmp));
920    }
921
922    /**
923     * <EMBED CLASS=defs DATA-DESC='does not start with any' DATA-CI='is not'>
924     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
925     * @param srcStr Any non-null instance of {@code java.lang.String}
926     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
927     * <EMBED CLASS='external-html' DATA-FILE-ID='SWNODELIM'>
928     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
929     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
930     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
931     * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
932     * @see #startsWithIgnoreCase(String, LV, String)
933     * @see #NAND(String, String, String[], Predicate)
934     */
935    public static boolean startsWithNAND_CI(String srcStr, int sPos, int ePos, String... tokens)
936    {
937        LV l = new LV(srcStr, sPos, ePos);
938        return NAND
939            ("startsWithNAND_CI", srcStr, tokens, cmp -> startsWithIgnoreCase(srcStr, l, cmp));
940    }
941
942
943    // ********************************************************************************************
944    // ********************************************************************************************
945    // Starts With, Ends With
946    // ********************************************************************************************
947    // ********************************************************************************************
948
949
950    /**
951     * <EMBED CLASS=defs DATA-FUNC='starts with' DATA-CI='is'>
952     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_1C_SE>
953     * @param srcStr Any non-null instance of {@code java.lang.String}
954     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
955     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
956     * @param token The {@code String} used in the comparison against {@code srcStr}
957     * <EMBED CLASS='external-html' DATA-FILE-ID='SWNODELIM'>
958     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_1C_SE>
959     * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
960     * @see #startsWith(String, LV, String)
961     */
962    public static boolean startsWith(String srcStr, int sPos, int ePos, String token)
963    { return startsWith(srcStr, new LV(srcStr, sPos, ePos), token); }
964
965    /**
966     * <EMBED CLASS=defs DATA-FUNC='starts with' DATA-CI='is not'>
967     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_1C_SE>
968     * @param srcStr Any non-null instance of {@code java.lang.String}
969     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
970     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
971     * @param token The {@code String} used in the comparison against {@code srcStr}
972     * <EMBED CLASS='external-html' DATA-FILE-ID='SWNODELIM'>
973     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_1C_SE>
974     * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
975     * @see #startsWithIgnoreCase(String, LV, String)
976     */
977    public static boolean startsWithIgnoreCase(String srcStr, int sPos, int ePos, String token)
978    { return startsWithIgnoreCase(srcStr, new LV(srcStr, sPos, ePos), token); }
979
980    /**
981     * <EMBED CLASS=defs DATA-FUNC='ends with' DATA-CI='is'>
982     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_1C_SE>
983     * @param srcStr Any non-null instance of {@code java.lang.String}
984     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
985     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
986     * @param token The {@code String} used in the comparison against {@code srcStr}
987     * <EMBED CLASS='external-html' DATA-FILE-ID='EWNODELIM'>
988     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_1C_SE>
989     * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
990     * @see #endsWith(String, LV, String)
991     */
992    public static boolean endsWith(String srcStr, int sPos, int ePos, String token)
993    { return endsWith(srcStr, new LV(srcStr, sPos, ePos), token); }
994
995    /**
996     * <EMBED CLASS=defs DATA-FUNC='ends with' DATA-CI='is not'>
997     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_1C_SE>
998     * @param srcStr Any non-null instance of {@code java.lang.String}
999     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
1000     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
1001     * @param token The {@code String} used in the comparison against {@code srcStr}
1002     * <EMBED CLASS='external-html' DATA-FILE-ID='EWNODELIM'>
1003     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_1C_SE>
1004     * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
1005     * @see #endsWithIgnoreCase(String, LV, String)
1006     */
1007    public static boolean endsWithIgnoreCase(String srcStr, int sPos, int ePos, String token)
1008    { return endsWithIgnoreCase(srcStr, new LV(srcStr, sPos, ePos), token); }
1009
1010    /**
1011     * <EMBED CLASS=defs DATA-FUNC='contains' DATA-CI='is'>
1012     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_1C_SE>
1013     * @param srcStr Any non-null instance of {@code java.lang.String}
1014     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
1015     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
1016     * @param token The {@code String} used in the comparison against {@code srcStr}
1017     * <EMBED CLASS='external-html' DATA-FILE-ID='CNNODELIM'>
1018     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_1C_SE>
1019     * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
1020     * @see #contains(String, LV, String)
1021     */
1022    public static boolean contains(String srcStr, int sPos, int ePos, String token)
1023    { return contains(srcStr, new LV(srcStr, sPos, ePos), token); }
1024
1025    /**
1026     * <EMBED CLASS=defs DATA-FUNC='contains' DATA-CI='is not'>
1027     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_1C_SE>
1028     * @param srcStr Any non-null instance of {@code java.lang.String}
1029     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
1030     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
1031     * @param token The {@code String} used in the comparison against {@code srcStr}
1032     * <EMBED CLASS='external-html' DATA-FILE-ID='CNNODELIM'>
1033     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_1C_SE>
1034     * @throws StringIndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
1035     * @see #containsIgnoreCase(String, LV, String)
1036     */
1037    public static boolean containsIgnoreCase(String srcStr, int sPos, int ePos, String token)
1038    { return containsIgnoreCase(srcStr, new LV(srcStr, sPos, ePos), token); }
1039
1040
1041    // ********************************************************************************************
1042    // ********************************************************************************************
1043    // LV - protected
1044    // ********************************************************************************************
1045    // ********************************************************************************************
1046
1047
1048    /**
1049     * This method remains {@code 'protected'} because it utilizes a specialized Loop-Control
1050     * Variable Class Version of {@code 'LV'}.  It is used internally by the search methods above.
1051     */
1052    protected static boolean startsWith(String srcStr, LV l, String token)
1053    {
1054        int tokenLen = token.length();
1055
1056        return      ((l.end - l.start) >= tokenLen) 
1057                &&  srcStr.regionMatches(l.start, token, 0, tokenLen)
1058                &&  (   ((l.start + tokenLen) == srcStr.length())
1059                    ||  Character.isWhitespace(srcStr.charAt(l.start + tokenLen)));
1060    }
1061
1062    /**
1063     * This method remains {@code 'protected'} because it utilizes a specialized Loop-Control
1064     * Variable Class Version of {@code 'LV'}.  It is used internally by the search methods above.
1065     */
1066    protected static boolean startsWithIgnoreCase(String srcStr, LV l, String token)
1067    {
1068        int tokenLen = token.length();
1069
1070        return      ((l.end - l.start) >= tokenLen) 
1071                &&  srcStr.regionMatches(true, l.start, token, 0, tokenLen)
1072                &&  (   ((l.start + tokenLen) == srcStr.length())
1073                    ||  Character.isWhitespace(srcStr.charAt(l.start + tokenLen)));
1074    }
1075
1076    /**
1077     * This method remains {@code 'protected'} because it utilizes a specialized Loop-Control
1078     * Variable Class Version of {@code 'LV'}.  It is used internally by the search methods above.
1079     */
1080    protected static boolean endsWith(String srcStr, LV l, String token)
1081    {
1082        int tokenLen = token.length();
1083
1084        return      ((l.end - l.start) >= tokenLen)
1085                &&  srcStr.regionMatches(l.end - tokenLen, token, 0, tokenLen)
1086                &&  (   ((l.end - tokenLen) == 0)
1087                    ||  Character.isWhitespace(srcStr.charAt(l.end - tokenLen - 1)));
1088    }
1089
1090    /**
1091     * This method remains {@code 'protected'} because it utilizes a specialized Loop-Control
1092     * Variable Class Version of {@code 'LV'}.  It is used internally by the search methods above.
1093     */
1094    protected static boolean endsWithIgnoreCase(String srcStr, LV l, String token)
1095    {
1096        int tokenLen = token.length();
1097    
1098        return      ((l.end - l.start) >= tokenLen)
1099                &&  srcStr.regionMatches(true, l.end - tokenLen, token, 0, tokenLen)
1100                &&  (   ((l.end - tokenLen) == 0)
1101                    ||  Character.isWhitespace(srcStr.charAt(l.end - tokenLen - 1)));
1102    }
1103
1104    /**
1105     * This method remains {@code 'protected'} because it utilizes a specialized Loop-Control
1106     * Variable Class Version of {@code 'LV'}.  It is used internally by the search methods above.
1107     */
1108    protected static boolean contains(String srcStr, LV l, String token)
1109    {
1110        // String.regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)
1111        // Tests if two string regions are equal.  A substring of this {@code String} object is
1112        // compared to a substring of the argument other.  The result is true if these substrings
1113        // represent character sequences that are the same, ignoring case if and only if ignoreCase
1114        // is true.
1115
1116        int tokenLen    = token.length();
1117        int loopLen     = l.end - tokenLen;
1118
1119        if ((l.end - l.start) < token.length()) return false;
1120
1121        for (int i=l.start; i <= loopLen; i++)
1122            if (    srcStr.regionMatches(i, token, 0, tokenLen)
1123                &&  (   (i == 0)
1124                    ||  Character.isWhitespace(srcStr.charAt(i-1)))
1125                &&  (   ((i + tokenLen) == srcStr.length())
1126                    ||  Character.isWhitespace(srcStr.charAt(i + tokenLen)))
1127                )
1128                return true;
1129
1130        return false;
1131    }
1132
1133    /**
1134     * This method remains {@code 'protected'} because it utilizes a specialized Loop-Control
1135     * Variable Class Version of {@code 'LV'}.  It is used internally by the search methods above.
1136     */
1137    protected static boolean containsIgnoreCase(String srcStr, LV l, String token)
1138    {
1139        // String.regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)
1140        // Tests if two string regions are equal.  A substring of this {@code String} object is
1141        // compared to a substring of the argument other.  The result is true if these substrings
1142        // represent character sequences that are the same, ignoring case if and only if ignoreCase
1143        // is true.
1144
1145        int tokenLen    = token.length();
1146        int loopLen     = l.end - tokenLen;
1147
1148        if ((l.end - l.start) < token.length()) return false;
1149
1150        for (int i=l.start; i <= loopLen; i++)
1151            if (    srcStr.regionMatches(true, i, token, 0, tokenLen)
1152                &&  (   (i == 0)
1153                    ||  Character.isWhitespace(srcStr.charAt(i-1)))
1154                &&  (   ((i + tokenLen) == srcStr.length())
1155                    ||  Character.isWhitespace(srcStr.charAt(i + tokenLen)))
1156                )
1157                return true;
1158
1159        return false;
1160    }
1161
1162
1163    // ********************************************************************************************
1164    // ********************************************************************************************
1165    // CONTAINS OPTIMIZATION
1166    // ********************************************************************************************
1167    // ********************************************************************************************
1168
1169
1170    /**
1171     * Signifies that an {@code 'AND'} operation is required, but only for methods that implement
1172     * one of the {@code 'contains'} variants.
1173     */
1174    protected static final byte AND   = 0;
1175
1176    /**
1177     * Signifies that an {@code 'AND'} operation is required, but only for methods that implement
1178     * one of the {@code 'contains'} variants.
1179     */
1180    protected static final byte OR    = 1;
1181
1182    /**
1183     * Signifies that an {@code 'AND'} operation is required, but only for methods that implement
1184     * one of the {@code 'contains'} variants.
1185     */
1186    protected static final byte NAND  = 2;
1187
1188    /**
1189     * Signifies that an {@code 'AND'} operation is required, but only for methods that implement
1190     * one of the {@code 'contains'} variants.
1191     */
1192    protected static final byte XOR   = 3;
1193
1194    private static final String CONTAINS_EX = 
1195        "The value passed to parameter 'booleanOperation' was [BOOL]." +
1196        "However, this parameter is intended to must be chosen from one of the four boolean " +
1197        "static-constants available in this class.  Valid values for this parameter include: " +
1198        "StrCmpr.AND, StrCmpr.OR, StrCmpr.XOR and StrCmpr.NAND.";
1199
1200    /**
1201     * Implementing a 'contains' is more efficient by performing only one loop iteration.
1202     * Therefore, the methods that implement some variant of the {@code String.contains} method
1203     * will use this general-purpose {@code contains}-testing method.
1204     * @param ignoresCase This is used to signify whether to ignore case when performing the
1205     * {@code String}-comparison operations.
1206     * @param booleanOperation This is designed to take one of four values.  This method will
1207     * throw an exception if it does not.
1208     * @param l Loop end-point parameter
1209     * @param srcStr Any non-null instance of {@code java.lang.String}
1210     * @param tokens This is one (or many) java {@code String's}, each of which shall be
1211     * checked whether it is contained by {@code 'srcStr'}.
1212     * @return The appropriate response based on the inputs for boolean logic.
1213     */
1214    protected static boolean CONTAINS(
1215        boolean ignoresCase, byte booleanOperation, LV l, String srcStr, String[] tokens
1216    )
1217    {
1218        int     len         = srcStr.length();
1219        int     count       = (booleanOperation == XOR) ? 0 : tokens.length;
1220        int[]   tokLenArr   = new int[tokens.length];
1221
1222        for (int i=0; i < tokens.length; i++) tokLenArr[i] = tokens[i].length();
1223
1224        for (int i=l.start; i < l.end; i++)
1225
1226            for (int j=0; j < tokens.length; j++)
1227
1228                if (tokLenArr[j] != -1)
1229
1230                    if (srcStr.regionMatches(ignoresCase, i, tokens[j], 0, tokLenArr[j]))
1231
1232                        if (    (   (i==0)
1233                                ||  Character.isWhitespace(srcStr.charAt(i-1)))
1234                            &&  (   ((i + tokLenArr[j]) == len)
1235                                ||  Character.isWhitespace(srcStr.charAt(i + tokLenArr[j])))
1236                        )
1237
1238                            switch (booleanOperation)
1239                            {
1240                                case AND    :   tokLenArr[j] = -1;
1241                                                if (--count == 0)   return true;
1242                                                else                break;
1243
1244                                case XOR    :   tokLenArr[j] = -1;
1245                                                if (++count > 1)    return false;
1246                                                else                break;
1247
1248                                case OR     :   return true;
1249
1250                                case NAND   :   return false;
1251
1252                                default     :   throw new IllegalArgumentException
1253                                                (CONTAINS_EX.replace("BOOL", "" + booleanOperation));
1254                            }
1255
1256        switch(booleanOperation)
1257        {
1258            case AND    : return false;
1259            case OR     : return false;
1260            case XOR    : return count == 1;
1261            case NAND   : return true;
1262            default     : throw new IllegalArgumentException
1263                            (CONTAINS_EX.replace("BOOL", "" + booleanOperation));
1264        }
1265    }
1266
1267    /**
1268     * Implementing a 'contains' is more efficient by performing only one loop iteration.
1269     * Therefore, the methods that implement some variant of the {@code String.contains} method
1270     * will use this general-purpose {@code contains}-testing method.
1271     * @param ignoresCase This is used to signify whether to ignore case when performing the
1272     * {@code String}-comparison operations.
1273     * @param booleanOperation This is designed to take one of four values.  This method will
1274     * throw an exception if it does not.
1275     * @param srcStr Any non-null instance of {@code java.lang.String}
1276     * @param tokens This is one (or many) java {@code String's}, each of which shall be
1277     * checked whether it is contained by {@code 'srcStr'}.
1278     * @return The appropriate response based on the inputs for boolean logic.
1279     */
1280    protected static boolean CONTAINS(
1281        boolean ignoresCase, byte booleanOperation, String srcStr, String[] tokens
1282    )
1283    {
1284        int     len         = srcStr.length();
1285        int     count       = (booleanOperation == XOR) ? 0 : tokens.length;
1286        int[]   tokLenArr   = new int[tokens.length];
1287
1288        for (int i=0; i < tokens.length; i++) tokLenArr[i] = tokens[i].length();
1289
1290        for (int i=0; i < len; i++)
1291
1292            for (int j=0; j < tokens.length; j++)
1293
1294                if (tokLenArr[j] != -1)
1295
1296                    if (srcStr.regionMatches(ignoresCase, i, tokens[j], 0, tokLenArr[j]))
1297
1298                        if (    (   (i==0)
1299                                ||  Character.isWhitespace(srcStr.charAt(i-1)))
1300                            &&  (   ((i + tokens[j].length()) == len)
1301                                ||  Character.isWhitespace(srcStr.charAt(i + tokens[j].length())))
1302                        )
1303                            switch (booleanOperation)
1304                            {
1305                                case AND    :   tokLenArr[j] = -1;
1306                                                if (--count == 0)   return true;
1307                                                else                break;
1308
1309                                case XOR    :   tokLenArr[j] = -1;
1310                                                if (++count > 1)    return false;
1311                                                else                break;
1312
1313                                case OR     :   return true;
1314
1315                                case NAND   :   return false;
1316
1317                                default     :   throw new IllegalArgumentException
1318                                                (CONTAINS_EX.replace("BOOL", "" + booleanOperation));
1319                            }
1320
1321        switch(booleanOperation)
1322        {
1323            case AND    : return false;
1324            case OR     : return false;
1325            case XOR    : return count == 1;
1326            case NAND   : return true;
1327            default     : throw new IllegalArgumentException
1328                            (CONTAINS_EX.replace("BOOL", "" + booleanOperation));
1329        }
1330    }
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357 
1358
1359    // ********************************************************************************************
1360    // ********************************************************************************************
1361    // ********************************************************************************************
1362    // ********************************************************************************************
1363    // ********************************************************************************************
1364    // ********************************************************************************************
1365    // StrCmpr Main Section
1366    // ********************************************************************************************
1367    // ********************************************************************************************
1368    // ********************************************************************************************
1369    // ********************************************************************************************
1370    // ********************************************************************************************
1371
1372
1373    
1374    // ********************************************************************************************
1375    // ********************************************************************************************
1376    // CONTAINS
1377    // ********************************************************************************************
1378    // ********************************************************************************************
1379
1380
1381    /**
1382     * <EMBED CLASS=defs DATA-DESC='contains at least one' DATA-CI='is'>
1383     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
1384     * @param srcStr Any non-null instance of {@code java.lang.String}
1385     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1386     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
1387     * <EMBED CLASS='external-html' DATA-FILE-ID='CNDELIM'>
1388     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
1389     * @see #CONTAINS(boolean, byte, String, String[])
1390     */
1391    public static boolean containsOR
1392        (String srcStr, Predicate<Character> extraDelimiterTest, String... tokens)
1393    { return CONTAINS(false, OR, srcStr, extraDelimiterTest, tokens); }
1394
1395    /**
1396     * <EMBED CLASS=defs DATA-DESC='contains every one' DATA-CI='is'>
1397     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
1398     * @param srcStr Any non-null instance of {@code java.lang.String}
1399     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1400     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
1401     * <EMBED CLASS='external-html' DATA-FILE-ID='CNDELIM'>
1402     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
1403     * @see #CONTAINS(boolean, byte, String, String[])
1404     */
1405    public static boolean containsAND
1406        (String srcStr, Predicate<Character> extraDelimiterTest, String... tokens)
1407    { return CONTAINS(false, AND, srcStr, extraDelimiterTest, tokens); }
1408
1409    /**
1410     * <EMBED CLASS=defs DATA-DESC='contains exactly one' DATA-CI='is'>
1411     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
1412     * @param srcStr Any non-null instance of {@code java.lang.String}
1413     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1414     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
1415     * <EMBED CLASS='external-html' DATA-FILE-ID='CNDELIM'>
1416     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
1417     * @see #CONTAINS(boolean, byte, String, String[])
1418     */
1419    public static boolean containsXOR
1420        (String srcStr, Predicate<Character> extraDelimiterTest, String... tokens)
1421    { return CONTAINS(false, XOR, srcStr, extraDelimiterTest, tokens); }
1422
1423    /**
1424     * <EMBED CLASS=defs DATA-DESC='does not contain any' DATA-CI='is'>
1425     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
1426     * @param srcStr Any non-null instance of {@code java.lang.String}
1427     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1428     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
1429     * <EMBED CLASS='external-html' DATA-FILE-ID='CNDELIM'>
1430     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
1431     * @see #CONTAINS(boolean, byte, String, String[])
1432     */
1433    public static boolean containsNAND
1434        (String srcStr, Predicate<Character> extraDelimiterTest, String... tokens)
1435    { return CONTAINS(false, NAND, srcStr, extraDelimiterTest, tokens); }
1436
1437    /**
1438     * <EMBED CLASS=defs DATA-DESC='contains at least one' DATA-CI='is not'>
1439     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
1440     * @param srcStr Any non-null instance of {@code java.lang.String}
1441     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1442     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
1443     * <EMBED CLASS='external-html' DATA-FILE-ID='CNDELIM'>
1444     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
1445     * @see #CONTAINS(boolean, byte, String, String[])
1446     */
1447    public static boolean containsOR_CI
1448        (String srcStr, Predicate<Character> extraDelimiterTest, String... tokens)
1449    { return CONTAINS(true, OR, srcStr, extraDelimiterTest, tokens); }
1450
1451    /**
1452     * <EMBED CLASS=defs DATA-DESC='contains every one' DATA-CI='is not'>
1453     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
1454     * @param srcStr Any non-null instance of {@code java.lang.String}
1455     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1456     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
1457     * <EMBED CLASS='external-html' DATA-FILE-ID='CNDELIM'>
1458     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
1459     * @see #CONTAINS(boolean, byte, String, String[])
1460     */
1461    public static boolean containsAND_CI
1462        (String srcStr, Predicate<Character> extraDelimiterTest, String... tokens)
1463    { return CONTAINS(true, AND, srcStr, extraDelimiterTest, tokens); }
1464
1465    /**
1466     * <EMBED CLASS=defs DATA-DESC='contains exactly one' DATA-CI='is not'>
1467     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
1468     * @param srcStr Any non-null instance of {@code java.lang.String}
1469     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1470     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
1471     * <EMBED CLASS='external-html' DATA-FILE-ID='CNDELIM'>
1472     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
1473     * @see #CONTAINS(boolean, byte, String, String[])
1474     */
1475    public static boolean containsXOR_CI
1476        (String srcStr, Predicate<Character> extraDelimiterTest, String... tokens)
1477    { return CONTAINS(true, XOR, srcStr, extraDelimiterTest, tokens); }
1478
1479    /**
1480     * <EMBED CLASS=defs DATA-DESC='does not contain any' DATA-CI='is not'>
1481     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
1482     * @param srcStr Any non-null instance of {@code java.lang.String}
1483     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1484     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
1485     * <EMBED CLASS='external-html' DATA-FILE-ID='CNDELIM'>
1486     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
1487     * @see #CONTAINS(boolean, byte, String, String[])
1488     */
1489    public static boolean containsNAND_CI
1490        (String srcStr, Predicate<Character> extraDelimiterTest, String... tokens)
1491    { return CONTAINS(true, NAND, srcStr, extraDelimiterTest, tokens); }
1492
1493
1494    // ********************************************************************************************
1495    // ********************************************************************************************
1496    // STARTS-WITH, ENDS-WITH
1497    // ********************************************************************************************
1498    // ********************************************************************************************
1499
1500
1501    /**
1502     * <EMBED CLASS=defs DATA-DESC='ends with exactly one' DATA-CI='is'>
1503     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
1504     * @param srcStr Any non-null instance of {@code java.lang.String}
1505     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1506     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
1507     * <EMBED CLASS='external-html' DATA-FILE-ID='EWDELIM'>
1508     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
1509     * @see #XOR(String, String, String[], Predicate)
1510     * @see #endsWith(String, LV, String)
1511     */
1512    public static boolean endsWithXOR
1513        (String srcStr, Predicate<Character> extraDelimiterTest, String... tokens)
1514    {
1515        return XOR(
1516            "endsWithXOR", srcStr, tokens,
1517            cmp -> endsWith(srcStr, new LV(srcStr, 0, -1), extraDelimiterTest, cmp)
1518        );
1519    }
1520
1521    /**
1522     * <EMBED CLASS=defs DATA-DESC='does not end with any' DATA-CI='is'>
1523     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
1524     * @param srcStr Any non-null instance of {@code java.lang.String}
1525     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1526     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
1527     * <EMBED CLASS='external-html' DATA-FILE-ID='EWDELIM'>
1528     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
1529     * @see #NAND(String, String, String[], Predicate)
1530     * @see #endsWith(String, LV, String)
1531     */
1532    public static boolean endsWithNAND
1533        (String srcStr, Predicate<Character> extraDelimiterTest, String... tokens)
1534    {
1535        return NAND(
1536            "endsWithNAND", srcStr, tokens,
1537            cmp -> endsWith(srcStr, new LV(srcStr, 0, -1), extraDelimiterTest, cmp)
1538        );
1539    }
1540
1541    /**
1542     * <EMBED CLASS=defs DATA-DESC='starts with exactly one' DATA-CI='is'>
1543     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
1544     * @param srcStr Any non-null instance of {@code java.lang.String}
1545     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1546     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
1547     * <EMBED CLASS='external-html' DATA-FILE-ID='SWDELIM'>
1548     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
1549     * @see #XOR(String, String, String[], Predicate)
1550     * @see #startsWith(String, LV, String)
1551     */
1552    public static boolean startsWithXOR
1553        (String srcStr, Predicate<Character> extraDelimiterTest, String... tokens)
1554    {
1555        return XOR(
1556            "startsWithXOR", srcStr, tokens,
1557            cmp -> startsWith(srcStr, new LV(srcStr, 0, -1), extraDelimiterTest, cmp)
1558        );
1559    }
1560
1561    /**
1562     * <EMBED CLASS=defs DATA-DESC='does not start with any' DATA-CI='is'>
1563     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
1564     * @param srcStr Any non-null instance of {@code java.lang.String}
1565     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1566     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
1567     * <EMBED CLASS='external-html' DATA-FILE-ID='SWDELIM'>
1568     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
1569     * @see #NAND(String, String, String[], Predicate)
1570     * @see #startsWith(String, LV, String)
1571     */
1572    public static boolean startsWithNAND
1573        (String srcStr, Predicate<Character> extraDelimiterTest, String... tokens)
1574    {
1575        return NAND(
1576            "startsWithNAND", srcStr, tokens,
1577            cmp -> startsWith(srcStr, new LV(srcStr, 0, -1), extraDelimiterTest, cmp)
1578        );
1579    }
1580
1581
1582    // ********************************************************************************************
1583    // ********************************************************************************************
1584    // STARTS-WITH, ENDS-WITH - CASE INSENSITIVE
1585    // ********************************************************************************************
1586    // ********************************************************************************************
1587
1588
1589    /**
1590     * <EMBED CLASS=defs DATA-DESC='ends with exactly one' DATA-CI='is not'>
1591     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
1592     * @param srcStr Any non-null instance of {@code java.lang.String}
1593     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1594     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
1595     * <EMBED CLASS='external-html' DATA-FILE-ID='EWDELIM'>
1596     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
1597     * @see #endsWithIgnoreCase(String, String)
1598     * @see #XOR(String, String, String[], Predicate)
1599     */
1600    public static boolean endsWithXOR_CI
1601        (String srcStr, Predicate<Character> extraDelimiterTest, String... tokens)
1602    {
1603        return XOR(
1604            "endsWithXOR_CI", srcStr, tokens,
1605            cmp -> endsWithIgnoreCase(srcStr, extraDelimiterTest, cmp)
1606        );
1607    }
1608
1609    /**
1610     * <EMBED CLASS=defs DATA-DESC='does not end with any' DATA-CI='is not'>
1611     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
1612     * @param srcStr Any non-null instance of {@code java.lang.String}
1613     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1614     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
1615     * <EMBED CLASS='external-html' DATA-FILE-ID='EWDELIM'>
1616     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
1617     * @see #endsWithIgnoreCase(String, String)
1618     * @see #NAND(String, String, String[], Predicate)
1619     */
1620    public static boolean endsWithNAND_CI
1621        (String srcStr, Predicate<Character> extraDelimiterTest, String... tokens)
1622    {
1623        return NAND(
1624            "endsWithNAND_CI", srcStr, tokens,
1625            cmp -> endsWithIgnoreCase(srcStr, extraDelimiterTest, cmp)
1626        );
1627    }
1628
1629    /**
1630     * <EMBED CLASS=defs DATA-DESC='starts with exactly one' DATA-CI='is not'>
1631     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
1632     * @param srcStr Any non-null instance of {@code java.lang.String}
1633     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1634     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
1635     * <EMBED CLASS='external-html' DATA-FILE-ID='SWDELIM'>
1636     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
1637     * @see #startsWithIgnoreCase(String, String)
1638     * @see #XOR(String, String, String[], Predicate)
1639     */
1640    public static boolean startsWithXOR_CI
1641        (String srcStr, Predicate<Character> extraDelimiterTest, String... tokens)
1642    {
1643        return XOR(
1644            "startsWithXOR_CI", srcStr, tokens,
1645            cmp -> startsWithIgnoreCase(srcStr, extraDelimiterTest, cmp)
1646        );
1647    }
1648
1649    /**
1650     * <EMBED CLASS=defs DATA-DESC='does not start with any' DATA-CI='is not'>
1651     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC>
1652     * @param srcStr Any non-null instance of {@code java.lang.String}
1653     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1654     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
1655     * <EMBED CLASS='external-html' DATA-FILE-ID='SWDELIM'>
1656     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET>
1657     * @see #startsWithIgnoreCase(String, String)
1658     * @see #NAND(String, String, String[], Predicate)
1659     */
1660    public static boolean startsWithNAND_CI
1661        (String srcStr, Predicate<Character> extraDelimiterTest, String... tokens)
1662    {
1663        return NAND(
1664            "startsWithNAND_CI", srcStr, tokens,
1665            cmp -> startsWithIgnoreCase(srcStr, extraDelimiterTest, cmp)
1666        );
1667    }
1668
1669
1670    // ********************************************************************************************
1671    // ********************************************************************************************
1672    // Three Standard Java Methods, Added Token Checking
1673    // ********************************************************************************************
1674    // ********************************************************************************************
1675
1676
1677    /**
1678     * <EMBED CLASS=defs DATA-FUNC='starts with' DATA-CI='is'>
1679     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_1C>
1680     * @param srcStr Any non-null instance of {@code java.lang.String}
1681     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1682     * @param token The {@code String} used in the comparison against {@code srcStr}
1683     * <EMBED CLASS='external-html' DATA-FILE-ID='SWDELIM'>
1684     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_1C>
1685     */
1686    public static boolean startsWith
1687        (String srcStr, Predicate<Character> extraDelimiterTest, String token)
1688    {
1689        return  srcStr.startsWith(token)
1690                &&  (   (token.length() == srcStr.length())
1691                    ||  Character.isWhitespace(srcStr.charAt(token.length()))
1692                    ||  extraDelimiterTest.test(srcStr.charAt(token.length())));
1693    }
1694
1695    /**
1696     * <EMBED CLASS=defs DATA-FUNC='ends with' DATA-CI='is'>
1697     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_1C>
1698     * @param srcStr Any non-null instance of {@code java.lang.String}
1699     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1700     * @param token The {@code String} used in the comparison against {@code srcStr}
1701     * <EMBED CLASS='external-html' DATA-FILE-ID='EWDELIM'>
1702     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_1C>
1703     */
1704    public static boolean endsWith
1705        (String srcStr, Predicate<Character> extraDelimiterTest, String token)
1706    {
1707        int tokenLen = token.length();
1708
1709        return  srcStr.endsWith(token)
1710                &&  (   ((srcStr.length() - tokenLen) == 0)
1711                    ||  Character.isWhitespace(srcStr.charAt(srcStr.length() - tokenLen - 1))
1712                    ||  extraDelimiterTest.test(srcStr.charAt(srcStr.length() - tokenLen - 1)));
1713    }
1714
1715    /**
1716     * <EMBED CLASS=defs DATA-FUNC='contains' DATA-CI='is'>
1717     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_1C>
1718     * @param srcStr Any non-null instance of {@code java.lang.String}
1719     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1720     * @param token The {@code String} used in the comparison against {@code srcStr}
1721     * <EMBED CLASS='external-html' DATA-FILE-ID='CNDELIM'>
1722     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_1C>
1723     */
1724    public static boolean contains
1725        (String srcStr, Predicate<Character> extraDelimiterTest, String token)
1726    { 
1727        int tokenLen    = token.length();
1728        int loopLen     = srcStr.length() - tokenLen;
1729
1730        for (int i=0; i <= loopLen; i++)
1731
1732            if (    srcStr.regionMatches(i, token, 0, tokenLen)
1733                &&  (   (i == 0)
1734                    ||  Character.isWhitespace(srcStr.charAt(i - 1))
1735                    ||  extraDelimiterTest.test(srcStr.charAt(i - 1)))
1736                &&  (   ((i + tokenLen) == srcStr.length())
1737                    ||  Character.isWhitespace(srcStr.charAt(i + tokenLen))
1738                    ||  extraDelimiterTest.test(srcStr.charAt(i + tokenLen)))
1739                )
1740
1741                return true;
1742
1743        return false;
1744    }
1745
1746
1747    // ********************************************************************************************
1748    // ********************************************************************************************
1749    // IGNORE-CASE METHODS
1750    // ********************************************************************************************
1751    // ********************************************************************************************
1752
1753
1754    /**
1755     * <EMBED CLASS=defs DATA-FUNC='starts with' DATA-CI='is not'>
1756     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_1C>
1757     * @param srcStr Any non-null instance of {@code java.lang.String}
1758     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1759     * @param token The {@code String} used in the comparison against {@code srcStr}
1760     * <EMBED CLASS='external-html' DATA-FILE-ID='SWDELIM'>
1761     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_1C>
1762     */
1763    public static boolean startsWithIgnoreCase
1764        (String srcStr, Predicate<Character> extraDelimiterTest, String token)
1765    {
1766        return  srcStr.regionMatches(true, 0, token, 0, token.length())
1767                &&  (   (token.length() == srcStr.length())
1768                    ||  Character.isWhitespace(srcStr.charAt(token.length()))
1769                    ||  extraDelimiterTest.test(srcStr.charAt(token.length())));
1770    }
1771
1772    /**
1773     * <EMBED CLASS=defs DATA-FUNC='ends with' DATA-CI='is not'>
1774     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_1C>
1775     * @param srcStr Any non-null instance of {@code java.lang.String}
1776     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1777     * @param token The {@code String} used in the comparison against {@code srcStr}
1778     * <EMBED CLASS='external-html' DATA-FILE-ID='EWDELIM'>
1779     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_1C>
1780     */
1781    public static boolean endsWithIgnoreCase
1782        (String srcStr, Predicate<Character> extraDelimiterTest, String token)
1783    {
1784        int tokenLen = token.length();
1785
1786        return  srcStr.regionMatches(true, srcStr.length() - tokenLen, token, 0, tokenLen)
1787                &&  (   ((srcStr.length() - tokenLen) == 0)
1788                    ||  Character.isWhitespace(srcStr.charAt(srcStr.length() - tokenLen - 1))
1789                    ||  extraDelimiterTest.test(srcStr.charAt(srcStr.length() - tokenLen - 1)));
1790    }
1791
1792    /**
1793     * <EMBED CLASS=defs DATA-FUNC='contains' DATA-CI='is not'>
1794     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_1C>
1795     * @param srcStr Any non-null instance of {@code java.lang.String}
1796     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1797     * @param token The {@code String} used in the comparison against {@code srcStr}
1798     * <EMBED CLASS='external-html' DATA-FILE-ID='CNDELIM'>
1799     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_1C>
1800     * @see #containsIgnoreCase(String, LV, String)
1801     */
1802    public static boolean containsIgnoreCase
1803        (String srcStr, Predicate<Character> extraDelimiterTest, String token)
1804    {
1805        return containsIgnoreCase
1806            (srcStr, new LV(srcStr, 0, srcStr.length()), extraDelimiterTest, token);
1807    }
1808
1809
1810
1811
1812
1813
1814
1815    // ********************************************************************************************
1816    // ********************************************************************************************
1817    // ********************************************************************************************
1818    // ********************************************************************************************
1819    // ********************************************************************************************
1820    // StrCmpr Main Section
1821    // ********************************************************************************************
1822    // ********************************************************************************************
1823    // ********************************************************************************************
1824    // ********************************************************************************************
1825    // ********************************************************************************************
1826
1827
1828
1829    // ********************************************************************************************
1830    // ********************************************************************************************
1831    // CONTAINS - Case Sensitive
1832    // ********************************************************************************************
1833    // ********************************************************************************************
1834
1835
1836    /**
1837     * <EMBED CLASS=defs DATA-DESC='contains at least one' DATA-CI='is'>
1838     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
1839     * @param srcStr Any non-null instance of {@code java.lang.String}
1840     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
1841     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
1842     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1843     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
1844     * <EMBED CLASS='external-html' DATA-FILE-ID='CNDELIM'>
1845     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
1846     * @throws StringIndexOutOfBoundsException
1847     * <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
1848     * @see #CONTAINS(boolean, byte, LV, String, String[])
1849     */
1850    public static boolean containsOR(
1851        String srcStr, int sPos, int ePos,
1852        Predicate<Character> extraDelimiterTest, String... tokens
1853    )
1854    {
1855        LV l = new LV(srcStr, sPos, ePos);
1856        return CONTAINS(false, OR, l, srcStr, extraDelimiterTest, tokens);
1857    }
1858
1859    /**
1860     * <EMBED CLASS=defs DATA-DESC='contains every one' DATA-CI='is'>
1861     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
1862     * @param srcStr Any non-null instance of {@code java.lang.String}
1863     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
1864     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
1865     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1866     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
1867     * <EMBED CLASS='external-html' DATA-FILE-ID='CNDELIM'>
1868     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
1869     * @throws StringIndexOutOfBoundsException
1870     * <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
1871     * @see #CONTAINS(boolean, byte, LV, String, String[])
1872     */
1873    public static boolean containsAND(
1874        String srcStr, int sPos, int ePos,
1875        Predicate<Character> extraDelimiterTest, String... tokens)
1876    {
1877        LV l = new LV(srcStr, sPos, ePos);
1878        return CONTAINS(false, AND, l, srcStr, extraDelimiterTest, tokens);
1879    }
1880
1881    /**
1882     * <EMBED CLASS=defs DATA-DESC='contains exactly one' DATA-CI='is'>
1883     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
1884     * @param srcStr Any non-null instance of {@code java.lang.String}
1885     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
1886     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
1887     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1888     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
1889     * <EMBED CLASS='external-html' DATA-FILE-ID='CNDELIM'>
1890     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
1891     * @throws StringIndexOutOfBoundsException
1892     * <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
1893     * @see #CONTAINS(boolean, byte, LV, String, String[])
1894     */
1895    public static boolean containsXOR(
1896        String srcStr, int sPos, int ePos,
1897        Predicate<Character> extraDelimiterTest, String... tokens
1898    )
1899    {
1900        LV l = new LV(srcStr, sPos, ePos);
1901        return CONTAINS(false, XOR, l, srcStr, extraDelimiterTest, tokens);
1902    }
1903
1904    /**
1905     * <EMBED CLASS=defs DATA-DESC='does not contain any' DATA-CI='is'>
1906     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
1907     * @param srcStr Any non-null instance of {@code java.lang.String}
1908     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
1909     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
1910     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1911     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
1912     * <EMBED CLASS='external-html' DATA-FILE-ID='CNDELIM'>
1913     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
1914     * @throws StringIndexOutOfBoundsException
1915     * <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
1916     * @see #CONTAINS(boolean, byte, LV, String, String[])
1917     */
1918    public static boolean containsNAND(
1919        String srcStr, int sPos, int ePos,
1920        Predicate<Character> extraDelimiterTest, String... tokens
1921    )
1922    {
1923        LV l = new LV(srcStr, sPos, ePos);
1924        return CONTAINS(false, NAND, l, srcStr, extraDelimiterTest, tokens);
1925    }
1926
1927
1928    // ********************************************************************************************
1929    // ********************************************************************************************
1930    // CONTAINS - Case In-Sensitive
1931    // ********************************************************************************************
1932    // ********************************************************************************************
1933
1934
1935    /**
1936     * <EMBED CLASS=defs DATA-DESC='contains at least one' DATA-CI='is not'>
1937     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
1938     * @param srcStr Any non-null instance of {@code java.lang.String}
1939     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
1940     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
1941     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1942     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
1943     * <EMBED CLASS='external-html' DATA-FILE-ID='CNDELIM'>
1944     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
1945     * @throws StringIndexOutOfBoundsException
1946     * <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
1947     * @see #CONTAINS(boolean, byte, LV, String, String[])
1948     */
1949    public static boolean containsOR_CI(
1950        String srcStr, int sPos, int ePos,
1951        Predicate<Character> extraDelimiterTest, String... tokens
1952    )
1953    {
1954        LV l = new LV(srcStr, sPos, ePos);
1955        return CONTAINS(true, OR, l, srcStr, extraDelimiterTest, tokens);
1956    }
1957
1958    /**
1959     * <EMBED CLASS=defs DATA-DESC='contains every one' DATA-CI='is not'>
1960     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
1961     * @param srcStr Any non-null instance of {@code java.lang.String}
1962     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
1963     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
1964     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1965     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
1966     * <EMBED CLASS='external-html' DATA-FILE-ID='CNDELIM'>
1967     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
1968     * @throws StringIndexOutOfBoundsException
1969     * <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
1970     * @see #CONTAINS(boolean, byte, LV, String, String[])
1971     */
1972    public static boolean containsAND_CI(
1973        String srcStr, int sPos, int ePos,
1974        Predicate<Character> extraDelimiterTest, String... tokens
1975    )
1976    {
1977        LV l = new LV(srcStr, sPos, ePos);
1978        return CONTAINS(true, AND, l, srcStr, extraDelimiterTest, tokens);
1979    }
1980
1981    /**
1982     * <EMBED CLASS=defs DATA-DESC='contains exactly one' DATA-CI='is not'>
1983     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
1984     * @param srcStr Any non-null instance of {@code java.lang.String}
1985     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
1986     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
1987     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
1988     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
1989     * <EMBED CLASS='external-html' DATA-FILE-ID='CNDELIM'>
1990     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
1991     * @throws StringIndexOutOfBoundsException
1992     * <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
1993     * @see #CONTAINS(boolean, byte, LV, String, String[])
1994     */
1995    public static boolean containsXOR_CI(
1996        String srcStr, int sPos, int ePos,
1997        Predicate<Character> extraDelimiterTest, String... tokens
1998    )
1999    {
2000        LV l = new LV(srcStr, sPos, ePos);
2001        return CONTAINS(true, XOR, l, srcStr, extraDelimiterTest, tokens);
2002    }
2003
2004    /**
2005     * <EMBED CLASS=defs DATA-DESC='does not contain any' DATA-CI='is not'>
2006     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
2007     * @param srcStr Any non-null instance of {@code java.lang.String}
2008     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
2009     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
2010     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
2011     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
2012     * <EMBED CLASS='external-html' DATA-FILE-ID='CNDELIM'>
2013     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
2014     * @throws StringIndexOutOfBoundsException
2015     * <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
2016     * @see #CONTAINS(boolean, byte, LV, String, String[])
2017     */
2018    public static boolean containsNAND_CI(
2019        String srcStr, int sPos, int ePos,
2020        Predicate<Character> extraDelimiterTest, String... tokens
2021    )
2022    {
2023        LV l = new LV(srcStr, sPos, ePos);
2024
2025        return CONTAINS(true, NAND, l, srcStr, extraDelimiterTest, tokens);
2026    }
2027
2028
2029    // ********************************************************************************************
2030    // ********************************************************************************************
2031    // STARTS-WITH, ENDS-WITH, Case-Sensitive
2032    // ********************************************************************************************
2033    // ********************************************************************************************
2034
2035
2036    /**
2037     * <EMBED CLASS=defs DATA-DESC='ends with exactly one' DATA-CI='is'>
2038     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
2039     * @param srcStr Any non-null instance of {@code java.lang.String}
2040     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
2041     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
2042     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
2043     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
2044     * <EMBED CLASS='external-html' DATA-FILE-ID='EWDELIM'>
2045     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
2046     * @throws StringIndexOutOfBoundsException
2047     * <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
2048     * @see #endsWith(String, LV, String)
2049     * @see #XOR(String, String, String[], Predicate)
2050     */
2051    public static boolean endsWithXOR(
2052        String srcStr, int sPos, int ePos,
2053        Predicate<Character> extraDelimiterTest, String... tokens
2054    )
2055    {
2056        LV l = new LV(srcStr, sPos, ePos);
2057
2058        return XOR(
2059            "endsWithXOR", srcStr, tokens,
2060            cmp -> endsWith(srcStr, l, extraDelimiterTest, cmp)
2061        );
2062    }
2063
2064    /**
2065     * <EMBED CLASS=defs DATA-DESC='does not end with any' DATA-CI='is'>
2066     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
2067     * @param srcStr Any non-null instance of {@code java.lang.String}
2068     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
2069     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
2070     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
2071     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
2072     * <EMBED CLASS='external-html' DATA-FILE-ID='EWDELIM'>
2073     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
2074     * @throws StringIndexOutOfBoundsException
2075     * <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
2076     * @see #endsWith(String, LV, String)
2077     * @see #NAND(String, String, String[], Predicate)
2078     */
2079    public static boolean endsWithNAND(
2080        String srcStr, int sPos, int ePos,
2081        Predicate<Character> extraDelimiterTest, String... tokens
2082    )
2083    {
2084        LV l = new LV(srcStr, sPos, ePos);
2085
2086        return NAND(
2087            "endsWithNAND", srcStr, tokens,
2088            cmp -> endsWith(srcStr, l, extraDelimiterTest, cmp)
2089        );
2090    }
2091
2092    /**
2093     * <EMBED CLASS=defs DATA-DESC='starts with exactly one' DATA-CI='is'>
2094     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
2095     * @param srcStr Any non-null instance of {@code java.lang.String}
2096     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
2097     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
2098     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
2099     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
2100     * <EMBED CLASS='external-html' DATA-FILE-ID='SWDELIM'>
2101     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
2102     * @throws StringIndexOutOfBoundsException
2103     * <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
2104     * @see #startsWith(String, LV, String)
2105     * @see #XOR(String, String, String[], Predicate)
2106     */
2107    public static boolean startsWithXOR(
2108        String srcStr, int sPos, int ePos,
2109        Predicate<Character> extraDelimiterTest, String... tokens
2110    )
2111    {
2112        LV l = new LV(srcStr, sPos, ePos);
2113
2114        return XOR(
2115            "startsWithXOR", srcStr, tokens,
2116            cmp -> startsWith(srcStr, l, extraDelimiterTest, cmp)
2117        );
2118    }
2119
2120    /**
2121     * <EMBED CLASS=defs DATA-DESC='does not start with any' DATA-CI='is'>
2122     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
2123     * @param srcStr Any non-null instance of {@code java.lang.String}
2124     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
2125     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
2126     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
2127     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
2128     * <EMBED CLASS='external-html' DATA-FILE-ID='SWDELIM'>
2129     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
2130     * @throws StringIndexOutOfBoundsException
2131     * <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
2132     * @see #startsWith(String, LV, String)
2133     * @see #NAND(String, String, String[], Predicate)
2134     */
2135    public static boolean startsWithNAND(
2136        String srcStr, int sPos, int ePos,
2137        Predicate<Character> extraDelimiterTest, String... tokens
2138    )
2139    {
2140        LV l = new LV(srcStr, sPos, ePos);
2141
2142        return NAND(
2143            "startsWithNAND", srcStr, tokens,
2144            cmp -> startsWith(srcStr, l, extraDelimiterTest, cmp)
2145        );
2146    }
2147
2148
2149    // ********************************************************************************************
2150    // ********************************************************************************************
2151    // STARTS-WITH, ENDS-WITH - CASE INSENSITIVE
2152    // ********************************************************************************************
2153    // ********************************************************************************************
2154
2155
2156    /**
2157     * <EMBED CLASS=defs DATA-DESC='ends with exactly one' DATA-CI='is not'>
2158     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
2159     * @param srcStr Any non-null instance of {@code java.lang.String}
2160     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
2161     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
2162     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
2163     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
2164     * <EMBED CLASS='external-html' DATA-FILE-ID='EWDELIM'>
2165     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
2166     * @throws StringIndexOutOfBoundsException
2167     * <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
2168     * @see #endsWithIgnoreCase(String, LV, String)
2169     * @see #XOR(String, String, String[], Predicate)
2170     */
2171    public static boolean endsWithXOR_CI(
2172        String srcStr, int sPos, int ePos,
2173        Predicate<Character> extraDelimiterTest, String... tokens
2174    )
2175    {
2176        LV l = new LV(srcStr, sPos, ePos);
2177
2178        return XOR(
2179            "endsWithXOR_CI", srcStr, tokens,
2180            cmp -> endsWithIgnoreCase(srcStr, l, extraDelimiterTest, cmp)
2181        );
2182    }
2183
2184    /**
2185     * <EMBED CLASS=defs DATA-DESC='does not ends with any' DATA-CI='is not'>
2186     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
2187     * @param srcStr Any non-null instance of {@code java.lang.String}
2188     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
2189     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
2190     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
2191     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
2192     * <EMBED CLASS='external-html' DATA-FILE-ID='EWDELIM'>
2193     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
2194     * @throws StringIndexOutOfBoundsException
2195     * <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
2196     * @see #endsWithIgnoreCase(String, LV, String)
2197     * @see #NAND(String, String, String[], Predicate)
2198     */
2199    public static boolean endsWithNAND_CI(
2200        String srcStr, int sPos, int ePos,
2201        Predicate<Character> extraDelimiterTest, String... tokens
2202    )
2203    {
2204        LV l = new LV(srcStr, sPos, ePos);
2205
2206        return NAND(
2207            "endsWithNAND_CI", srcStr, tokens,
2208            cmp -> endsWithIgnoreCase(srcStr, l, extraDelimiterTest, cmp)
2209        );
2210    }
2211
2212    /**
2213     * <EMBED CLASS=defs DATA-DESC='starts with exactly one' DATA-CI='is not'>
2214     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
2215     * @param srcStr Any non-null instance of {@code java.lang.String}
2216     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
2217     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
2218     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
2219     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
2220     * <EMBED CLASS='external-html' DATA-FILE-ID='SWDELIM'>
2221     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
2222     * @throws StringIndexOutOfBoundsException
2223     * <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
2224     * @see #startsWithIgnoreCase(String, LV, String)
2225     * @see #XOR(String, String, String[], Predicate)
2226     */
2227    public static boolean startsWithXOR_CI(
2228        String srcStr, int sPos, int ePos,
2229        Predicate<Character> extraDelimiterTest, String... tokens
2230    )
2231    {
2232        LV l = new LV(srcStr, sPos, ePos);
2233
2234        return XOR(
2235            "startsWithXOR_CI", srcStr, tokens,
2236            cmp -> startsWithIgnoreCase(srcStr, l, extraDelimiterTest, cmp)
2237        );
2238    }
2239
2240    /**
2241     * <EMBED CLASS=defs DATA-DESC='does not start with any' DATA-CI='is not'>
2242     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_SE>
2243     * @param srcStr Any non-null instance of {@code java.lang.String}
2244     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
2245     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
2246     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
2247     * @param tokens The {@code String's} used in the comparison against {@code 'srcStr'}
2248     * <EMBED CLASS='external-html' DATA-FILE-ID='SWDELIM'>
2249     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_SE>
2250     * @throws StringIndexOutOfBoundsException
2251     * <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
2252     * @see #startsWithIgnoreCase(String, LV, String)
2253     * @see #NAND(String, String, String[], Predicate)
2254     */
2255    public static boolean startsWithNAND_CI(
2256        String srcStr, int sPos, int ePos,
2257        Predicate<Character> extraDelimiterTest, String... tokens
2258    )
2259    {
2260        LV l = new LV(srcStr, sPos, ePos);
2261
2262        return NAND(
2263            "startsWithNAND_CI", srcStr, tokens,
2264            cmp -> startsWithIgnoreCase(srcStr, l, extraDelimiterTest, cmp)
2265        );
2266    }
2267
2268
2269    // ********************************************************************************************
2270    // ********************************************************************************************
2271    // simple, with "extra-delimiter"
2272    // ********************************************************************************************
2273    // ********************************************************************************************
2274
2275
2276    /**
2277     * <EMBED CLASS=defs DATA-FUNC='starts with' DATA-CI='is'>
2278     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_1C_SE>
2279     * @param srcStr Any non-null instance of {@code java.lang.String}
2280     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
2281     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
2282     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
2283     * @param token The {@code String} used in the comparison against {@code srcStr}
2284     * <EMBED CLASS='external-html' DATA-FILE-ID='SWDELIM'>
2285     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_1C_SE>
2286     * @throws StringIndexOutOfBoundsException
2287     * <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
2288     * @see #startsWith(String, LV, String)
2289     */
2290    public static boolean startsWith
2291        (String srcStr, int sPos, int ePos, Predicate<Character> extraDelimiterTest, String token)
2292    { return startsWith(srcStr, new LV(srcStr, sPos, ePos), extraDelimiterTest, token); }
2293
2294    /**
2295     * <EMBED CLASS=defs DATA-FUNC='starts with' DATA-CI='is not'>
2296     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_1C_SE>
2297     * @param srcStr Any non-null instance of {@code java.lang.String}
2298     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
2299     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
2300     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
2301     * @param token The {@code String} used in the comparison against {@code srcStr}
2302     * <EMBED CLASS='external-html' DATA-FILE-ID='SWDELIM'>
2303     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_1C_SE>
2304     * @throws StringIndexOutOfBoundsException
2305     * <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
2306     * @see #startsWithIgnoreCase(String, LV, String)
2307     */
2308    public static boolean startsWithIgnoreCase
2309        (String srcStr, int sPos, int ePos, Predicate<Character> extraDelimiterTest, String token)
2310    { return startsWithIgnoreCase(srcStr, new LV(srcStr, sPos, ePos), extraDelimiterTest, token); }
2311
2312    /**
2313     * <EMBED CLASS=defs DATA-FUNC='ends with' DATA-CI='is'>
2314     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_1C_SE>
2315     * @param srcStr Any non-null instance of {@code java.lang.String}
2316     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
2317     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
2318     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
2319     * @param token The {@code String} used in the comparison against {@code srcStr}
2320     * <EMBED CLASS='external-html' DATA-FILE-ID='EWDELIM'>
2321     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_1C_SE>
2322     * @throws StringIndexOutOfBoundsException
2323     * <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
2324     * @see #endsWith(String, LV, String)
2325     */
2326    public static boolean endsWith
2327        (String srcStr, int sPos, int ePos, Predicate<Character> extraDelimiterTest, String token)
2328    { return endsWith(srcStr, new LV(srcStr, sPos, ePos), extraDelimiterTest, token); }
2329
2330    /**
2331     * <EMBED CLASS=defs DATA-FUNC='ends with' DATA-CI='is not'>
2332     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_1C_SE>
2333     * @param srcStr Any non-null instance of {@code java.lang.String}
2334     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
2335     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
2336     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
2337     * @param token The {@code String} used in the comparison against {@code srcStr}
2338     * <EMBED CLASS='external-html' DATA-FILE-ID='EWDELIM'>
2339     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_1C_SE>
2340     * @throws StringIndexOutOfBoundsException
2341     * <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
2342     * @see #endsWithIgnoreCase(String, LV, String)
2343     */
2344    public static boolean endsWithIgnoreCase
2345        (String srcStr, int sPos, int ePos, Predicate<Character> extraDelimiterTest, String token)
2346    { return endsWithIgnoreCase(srcStr, new LV(srcStr, sPos, ePos), extraDelimiterTest, token); }
2347
2348    /**
2349     * <EMBED CLASS=defs DATA-FUNC='contains' DATA-CI='is'>
2350     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_1C_SE>
2351     * @param srcStr Any non-null instance of {@code java.lang.String}
2352     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
2353     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
2354     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
2355     * @param token The {@code String} used in the comparison against {@code srcStr}
2356     * <EMBED CLASS='external-html' DATA-FILE-ID='CNDELIM'>
2357     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_1C_SE>
2358     * @throws StringIndexOutOfBoundsException
2359     * <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
2360     * @see #contains(String, LV, String)
2361     */
2362    public static boolean contains
2363        (String srcStr, int sPos, int ePos, Predicate<Character> extraDelimiterTest, String token)
2364    { return contains(srcStr, new LV(srcStr, sPos, ePos), extraDelimiterTest, token); }
2365
2366    /**
2367     * <EMBED CLASS=defs DATA-FUNC='contains' DATA-CI='is not'>
2368     * <EMBED CLASS='external-html' DATA-FILE-ID=STC_DESC_1C_SE>
2369     * @param srcStr Any non-null instance of {@code java.lang.String}
2370     * @param sPos <EMBED CLASS='external-html' DATA-FILE-ID=SPOSSTR>
2371     * @param ePos <EMBED CLASS='external-html' DATA-FILE-ID=EPOSSTR>
2372     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
2373     * @param token The {@code String} used in the comparison against {@code srcStr}
2374     * <EMBED CLASS='external-html' DATA-FILE-ID='CNDELIM'>
2375     * @return <EMBED CLASS='external-html' DATA-FILE-ID=STC_RET_1C_SE>
2376     * @throws StringIndexOutOfBoundsException
2377     * <EMBED CLASS='external-html' DATA-FILE-ID=SIOOB_EX>
2378     * @see #containsIgnoreCase(String, LV, String)
2379     */
2380    public static boolean containsIgnoreCase
2381        (String srcStr, int sPos, int ePos, Predicate<Character> extraDelimiterTest, String token)
2382    { return containsIgnoreCase(srcStr, new LV(srcStr, sPos, ePos), extraDelimiterTest, token); }
2383
2384
2385    // ********************************************************************************************
2386    // ********************************************************************************************
2387    // PROTECTED, LV, Extra-Delimiter
2388    // ********************************************************************************************
2389    // ********************************************************************************************
2390
2391
2392    /**
2393     * This method remains {@code 'protected'} because it utilizes a specialized Loop-Control
2394     * Variable Class Version of {@code 'LV'}.  It is used internally by the search methods above.
2395     */
2396    protected static boolean startsWith
2397        (String srcStr, LV l, Predicate<Character> extraDelimiterTest, String token)
2398    {
2399        int tokenLen = token.length();
2400
2401        return      ((l.end - l.start) >= tokenLen) 
2402                &&  srcStr.regionMatches(l.start, token, 0, tokenLen)
2403                &&  (   ((l.start + tokenLen) == srcStr.length())
2404                    ||  Character.isWhitespace(srcStr.charAt(l.start + tokenLen))
2405                    ||  extraDelimiterTest.test(srcStr.charAt(l.start + tokenLen)));
2406    }
2407
2408    /**
2409     * This method remains {@code 'protected'} because it utilizes a specialized Loop-Control
2410     * Variable Class Version of {@code 'LV'}.  It is used internally by the search methods above.
2411     */
2412    protected static boolean startsWithIgnoreCase
2413        (String srcStr, LV l, Predicate<Character> extraDelimiterTest, String token)
2414    {
2415        int tokenLen = token.length();
2416
2417        return      ((l.end - l.start) >= tokenLen) 
2418                &&  srcStr.regionMatches(true, l.start, token, 0, tokenLen)
2419                &&  (   ((l.start + tokenLen) == srcStr.length())
2420                    ||  Character.isWhitespace(srcStr.charAt(l.start + tokenLen))
2421                    ||  extraDelimiterTest.test(srcStr.charAt(l.start + tokenLen)));
2422    }
2423
2424    /**
2425     * This method remains {@code 'protected'} because it utilizes a specialized Loop-Control
2426     * Variable Class Version of {@code 'LV'}.  It is used internally by the search methods above.
2427     */
2428    protected static boolean endsWith
2429        (String srcStr, LV l, Predicate<Character> extraDelimiterTest, String token)
2430    {
2431        int tokenLen = token.length();
2432
2433        return      ((l.end - l.start) >= tokenLen)
2434                &&  srcStr.regionMatches(l.end - tokenLen, token, 0, tokenLen)
2435                &&  (   ((l.end - tokenLen) == 0)
2436                    ||  Character.isWhitespace(srcStr.charAt(l.end - tokenLen - 1))
2437                    ||  extraDelimiterTest.test(srcStr.charAt(l.end - tokenLen - 1)));
2438    }
2439
2440    /**
2441     * This method remains {@code 'protected'} because it utilizes a specialized Loop-Control
2442     * Variable Class Version of {@code 'LV'}.  It is used internally by the search methods above.
2443     */
2444    protected static boolean endsWithIgnoreCase
2445        (String srcStr, LV l, Predicate<Character> extraDelimiterTest, String token)
2446    {
2447        int tokenLen = token.length();
2448    
2449        return      ((l.end - l.start) >= tokenLen)
2450                &&  srcStr.regionMatches(true, l.end - tokenLen, token, 0, tokenLen)
2451                &&  (   ((l.end - tokenLen) == 0)
2452                    ||  Character.isWhitespace(srcStr.charAt(l.end - tokenLen - 1))
2453                    ||  extraDelimiterTest.test(srcStr.charAt(l.end - tokenLen - 1)));
2454    }
2455
2456    /**
2457     * This method remains {@code 'protected'} because it utilizes a specialized Loop-Control
2458     * Variable Class Version of {@code 'LV'}.  It is used internally by the search methods above.
2459     */
2460    protected static boolean contains
2461        (String srcStr, LV l, Predicate<Character> extraDelimiterTest, String token)
2462    {
2463        // String.regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)
2464        // Tests if two string regions are equal.  A substring of this {@code String} object is
2465        // compared to a substring of the argument other.  The result is true if these substrings
2466        // represent character sequences that are the same, ignoring case if and only if ignoreCase
2467        // is true.
2468
2469        int tokenLen    = token.length();
2470        int loopLen     = l.end - tokenLen;
2471
2472        if ((l.end - l.start) < token.length()) return false;
2473
2474        for (int i=l.start; i <= loopLen; i++)
2475            if (    srcStr.regionMatches(i, token, 0, tokenLen)
2476                &&  (   (i == 0)
2477                    ||  Character.isWhitespace(srcStr.charAt(i-1))
2478                    ||  extraDelimiterTest.test(srcStr.charAt(i-1)))
2479                &&  (   ((i + tokenLen) == srcStr.length())
2480                    ||  Character.isWhitespace(srcStr.charAt(i + tokenLen))
2481                    ||  extraDelimiterTest.test(srcStr.charAt(i + tokenLen)))
2482                )
2483                return true;
2484
2485        return false;
2486    }
2487
2488    /**
2489     * This method remains {@code 'protected'} because it utilizes a specialized Loop-Control
2490     * Variable Class Version of {@code 'LV'}.  It is used internally by the search methods above.
2491     */
2492    protected static boolean containsIgnoreCase
2493        (String srcStr, LV l, Predicate<Character> extraDelimiterTest, String token)
2494    {
2495        // String.regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)
2496        // Tests if two string regions are equal.  A substring of this {@code String} object is
2497        // compared to a substring of the argument other.  The result is true if these substrings
2498        // represent character sequences that are the same, ignoring case if and only if ignoreCase
2499        // is true.
2500
2501        int tokenLen    = token.length();
2502        int loopLen     = l.end - tokenLen;
2503
2504        if ((l.end - l.start) < token.length()) return false;
2505
2506        for (int i=l.start; i <= loopLen; i++)
2507            if (    srcStr.regionMatches(true, i, token, 0, tokenLen)
2508                &&  (   (i == 0)
2509                    ||  Character.isWhitespace(srcStr.charAt(i-1))
2510                    ||  extraDelimiterTest.test(srcStr.charAt(i-1)))
2511                &&  (   ((i + tokenLen) == srcStr.length())
2512                    ||  Character.isWhitespace(srcStr.charAt(i + tokenLen))
2513                    ||  extraDelimiterTest.test(srcStr.charAt(i + tokenLen)))
2514                )
2515                return true;
2516
2517        return false;
2518    }
2519
2520
2521    // ********************************************************************************************
2522    // ********************************************************************************************
2523    // PROTECTED, CONTAINS,  Ezekiel 25:17, Grave-Vengeance and Furious Anger
2524    // ********************************************************************************************
2525    // ********************************************************************************************
2526
2527
2528    /**
2529     * Implementing a 'contains' is more efficient by performing only one loop iteration.
2530     * Therefore, the methods that implement some variant of the {@code String.contains} method
2531     * will use this general-purpose {@code contains}-testing method.
2532     * @param ignoresCase This is used to signify whether to ignore case when performing the
2533     * {@code String}-comparison operations.
2534     * @param booleanOperation This is designed to take one of four values.  This method will
2535     * throw an exception if it does not.
2536     * @param l Loop end-point parameter
2537     * @param srcStr Any non-null instance of {@code java.lang.String}
2538     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
2539     * @param tokens This is one (or many) java {@code String's}, each of which shall be
2540     * checked whether it is contained by {@code 'srcStr'}.
2541     * @return The appropriate response based on the inputs for boolean logic.
2542     */
2543    protected static boolean CONTAINS(
2544        boolean ignoresCase, byte booleanOperation, LV l, String srcStr,
2545        Predicate<Character> extraDelimiterTest, String[] tokens
2546    )
2547    {
2548        int     len         = srcStr.length();
2549        int     count       = (booleanOperation == XOR) ? 0 : tokens.length;
2550        int[]   tokLenArr   = new int[tokens.length];
2551        
2552        for (int i=0; i < tokLenArr.length; i++) tokLenArr[i] = tokens[i].length();
2553
2554        for (int i=l.start; i < l.end; i++)
2555            for (int j=0; j < tokens.length; j++)
2556                if (tokLenArr[j] != -1)
2557                    if (srcStr.regionMatches(ignoresCase, i, tokens[j], 0, tokLenArr[j]))
2558                        if (    (   (i==0)
2559                                ||  Character.isWhitespace(srcStr.charAt(i-1))
2560                                ||  extraDelimiterTest.test(srcStr.charAt(i-1)))
2561                            &&  (   ((i + tokLenArr[j]) == len)
2562                                ||  Character.isWhitespace(srcStr.charAt(i + tokLenArr[j]))
2563                                ||  extraDelimiterTest.test(srcStr.charAt(i + tokLenArr[j])))
2564                        )
2565                            switch (booleanOperation)
2566                            {
2567                                case AND    :   tokLenArr[j] = -1;
2568                                                if (--count == 0)   return true;
2569                                                else                break;
2570                                case XOR    :   tokLenArr[j] = -1;
2571                                                if (++count > 1)    return false;
2572                                                else                break;
2573                                case OR     :   return true;
2574                                case NAND   :   return false;
2575                                default     :   throw new IllegalArgumentException
2576                                                (CONTAINS_EX.replace("BOOL", "" + booleanOperation));
2577                            }
2578
2579        switch(booleanOperation)
2580        {
2581            case AND    : return false;
2582            case OR     : return false;
2583            case XOR    : return count == 1;
2584            case NAND   : return true;
2585            default     : throw new IllegalArgumentException
2586                            (CONTAINS_EX.replace("BOOL", "" + booleanOperation));
2587        }
2588    }
2589
2590    /**
2591     * Implementing a 'contains' is more efficient by performing only one loop iteration.
2592     * Therefore, the methods that implement some variant of the {@code String.contains} method
2593     * will use this general-purpose {@code contains}-testing method.
2594     * @param ignoresCase This is used to signify whether to ignore case when performing the
2595     * {@code String}-comparison operations.
2596     * @param booleanOperation This is designed to take one of four values.  This method will
2597     * throw an exception if it does not.
2598     * @param srcStr Any non-null instance of {@code java.lang.String}
2599     * @param extraDelimiterTest <EMBED CLASS='external-html' DATA-FILE-ID='XTRADELIM'>
2600     * @param tokens This is one (or many) java {@code String's}, each of which shall be
2601     * checked whether it is contained by {@code 'srcStr'}.
2602     * @return The appropriate response based on the inputs for boolean logic.
2603     */
2604    protected static boolean CONTAINS(
2605        boolean ignoresCase, byte booleanOperation, String srcStr, 
2606        Predicate<Character> extraDelimiterTest, String[] tokens
2607    )
2608    {
2609        int     count       = (booleanOperation == XOR) ? 0 : tokens.length;
2610        int     len         = srcStr.length();
2611        int[]   tokLenArr   = new int[tokens.length];
2612        
2613        for (int i=0; i < tokLenArr.length; i++) tokLenArr[i] = tokens[i].length();
2614
2615        for (int i=0; i < len; i++)
2616            for (int j=0; j < tokens.length; j++)
2617                if (tokLenArr[j] != -1)
2618                    if (srcStr.regionMatches(ignoresCase, i, tokens[j], 0, tokLenArr[j]))
2619                        if (    (   (i==0)
2620                                ||  Character.isWhitespace(srcStr.charAt(i-1))
2621                                ||  extraDelimiterTest.test(srcStr.charAt(i-1)))
2622                            &&  (   ((i+tokLenArr[j]) == len)
2623                                ||  Character.isWhitespace(srcStr.charAt(i+tokLenArr[j]))
2624                                ||  extraDelimiterTest.test(srcStr.charAt(i+tokLenArr[j])))
2625                        )
2626                            switch (booleanOperation)
2627                            {
2628                                case AND    :   tokLenArr[j] = -1;
2629                                                if (--count == 0)   return true;
2630                                                else                break;
2631                                case XOR    :   tokLenArr[j] = -1;
2632                                                if (++count > 1)    return false;
2633                                                else                break;
2634                                case OR     :   return true;
2635                                case NAND   :   return false;
2636                                default     :   throw new IllegalArgumentException
2637                                                (CONTAINS_EX.replace("BOOL", "" + booleanOperation));
2638                            }
2639
2640        switch(booleanOperation)
2641        {
2642            case AND    : return false;
2643            case OR     : return false;
2644            case XOR    : return count == 1;
2645            case NAND   : return true;
2646            default     : throw new IllegalArgumentException
2647                            (CONTAINS_EX.replace("BOOL", "" + booleanOperation));
2648        }
2649    }
2650
2651}