    001/*
    002* Licensed to the Apache Software Foundation (ASF) under one or more
    003* contributor license agreements.  See the NOTICE file distributed with
    004* this work for additional information regarding copyright ownership.
    005* The ASF licenses this file to You under the Apache License, Version 2.0
    006* (the "License"); you may not use this file except in compliance with
    007* the License.  You may obtain a copy of the License at
    008*
    009*      http://www.apache.org/licenses/LICENSE-2.0
    010*
    011* Unless required by applicable law or agreed to in writing, software
    012* distributed under the License is distributed on an "AS IS" BASIS,
    013* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014* See the License for the specific language governing permissions and
    015* limitations under the License.
    016*/
    017
    018package co.aikar.commands.apachecommonslang;
    019
    020import java.lang.reflect.Array;
    021import java.util.Iterator;
    022
    023/**
    024 * Select methods copied from Apache Commons to avoid importing entire lib
    025 * No changes to logic
    026 */
    027public class ApacheCommonsLangUtil {
    028
    029    /**
    030     * The empty String {@code ""}.
    031     * @since 2.0
    032     */
    033    public static final String EMPTY = "";
    034    /**
    035     * <p>Shallow clones an array returning a typecast result and handling
    036     * {@code null}.
    037     *
    038     * <p>The objects in the array are not cloned, thus there is no special
    039     * handling for multi-dimensional arrays.
    040     *
    041     * <p>This method returns {@code null} for a {@code null} input array.
    042     *
    043     * @param <T> the component type of the array
    044     * @param array  the array to shallow clone, may be {@code null}
    045     * @return the cloned array, {@code null} if {@code null} input
    046     */
    047    public static <T> T[] clone(final T[] array) {
    048        if (array == null) {
    049            return null;
    050        }
    051        return array.clone();
    052    }
    053
    054    /**
    055     * <p>Adds all the elements of the given arrays into a new array.
    056     * <p>The new array contains all of the element of {@code array1} followed
    057     * by all of the elements {@code array2}. When an array is returned, it is always
    058     * a new array.
    059     *
    060     * <pre>
    061     * ArrayUtils.addAll(null, null)     = null
    062     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
    063     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
    064     * ArrayUtils.addAll([], [])         = []
    065     * ArrayUtils.addAll([null], [null]) = [null, null]
    066     * ArrayUtils.addAll(["a", "b", "c"], ["1", "2", "3"]) = ["a", "b", "c", "1", "2", "3"]
    067     * </pre>
    068     *
    069     * @param <T> the component type of the array
    070     * @param array1  the first array whose elements are added to the new array, may be {@code null}
    071     * @param array2  the second array whose elements are added to the new array, may be {@code null}
    072     * @return The new array, {@code null} if both arrays are {@code null}.
    073     *      The type of the new array is the type of the first array,
    074     *      unless the first array is null, in which case the type is the same as the second array.
    075     * @since 2.1
    076     * @throws IllegalArgumentException if the array types are incompatible
    077     */
    078    public static <T> T[] addAll(final T[] array1, final T... array2) {
    079        if (array1 == null) {
    080            return clone(array2);
    081        } else if (array2 == null) {
    082            return clone(array1);
    083        }
    084        final Class<?> type1 = array1.getClass().getComponentType();
    085        @SuppressWarnings("unchecked") // OK, because array is of type T
    086        final T[] joinedArray = (T[]) Array.newInstance(type1, array1.length + array2.length);
    087        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
    088        try {
    089            System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
    090        } catch (final ArrayStoreException ase) {
    091            // Check if problem was due to incompatible types
    092            /*
    093             * We do this here, rather than before the copy because:
    094             * - it would be a wasted check most of the time
    095             * - safer, in case check turns out to be too strict
    096             */
    097            final Class<?> type2 = array2.getClass().getComponentType();
    098            if (!type1.isAssignableFrom(type2)) {
    099                throw new IllegalArgumentException("Cannot store " + type2.getName() + " in an array of "
    100                        + type1.getName(), ase);
    101            }
    102            throw ase; // No, so rethrow original
    103        }
    104        return joinedArray;
    105    }
    106
    107    //-----------------------------------------------------------------------
    108    /**
    109     * <p>Converts all the whitespace separated words in a String into capitalized words,
    110     * that is each word is made up of a titlecase character and then a series of
    111     * lowercase characters.  </p>
    112     *
    113     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.
    114     * A <code>null</code> input String returns <code>null</code>.
    115     * Capitalization uses the Unicode title case, normally equivalent to
    116     * upper case.</p>
    117     *
    118     * <pre>
    119     * WordUtils.capitalizeFully(null)        = null
    120     * WordUtils.capitalizeFully("")          = ""
    121     * WordUtils.capitalizeFully("i am FINE") = "I Am Fine"
    122     * </pre>
    123     *
    124     * @param str  the String to capitalize, may be null
    125     * @return capitalized String, <code>null</code> if null String input
    126     */
    127    public static String capitalizeFully(final String str) {
    128        return capitalizeFully(str, null);
    129    }
    130
    131    /**
    132     * <p>Converts all the delimiter separated words in a String into capitalized words,
    133     * that is each word is made up of a titlecase character and then a series of
    134     * lowercase characters. </p>
    135     *
    136     * <p>The delimiters represent a set of characters understood to separate words.
    137     * The first string character and the first non-delimiter character after a
    138     * delimiter will be capitalized. </p>
    139     *
    140     * <p>A <code>null</code> input String returns <code>null</code>.
    141     * Capitalization uses the Unicode title case, normally equivalent to
    142     * upper case.</p>
    143     *
    144     * <pre>
    145     * WordUtils.capitalizeFully(null, *)            = null
    146     * WordUtils.capitalizeFully("", *)              = ""
    147     * WordUtils.capitalizeFully(*, null)            = *
    148     * WordUtils.capitalizeFully(*, new char[0])     = *
    149     * WordUtils.capitalizeFully("i aM.fine", {'.'}) = "I am.Fine"
    150     * </pre>
    151     *
    152     * @param str  the String to capitalize, may be null
    153     * @param delimiters  set of characters to determine capitalization, null means whitespace
    154     * @return capitalized String, <code>null</code> if null String input
    155     * @since 2.1
    156     */
    157    public static String capitalizeFully(String str, final char... delimiters) {
    158        final int delimLen = delimiters == null ? -1 : delimiters.length;
    159        if (str == null || str.isEmpty() || delimLen == 0) {
    160            return str;
    161        }
    162        str = str.toLowerCase();
    163        return capitalize(str, delimiters);
    164    }
    165
    166    // Capitalizing
    167    //-----------------------------------------------------------------------
    168    /**
    169     * <p>Capitalizes all the whitespace separated words in a String.
    170     * Only the first character of each word is changed. To convert the
    171     * rest of each word to lowercase at the same time,
    172     * use {@link #capitalizeFully(String)}.</p>
    173     *
    174     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.
    175     * A <code>null</code> input String returns <code>null</code>.
    176     * Capitalization uses the Unicode title case, normally equivalent to
    177     * upper case.</p>
    178     *
    179     * <pre>
    180     * WordUtils.capitalize(null)        = null
    181     * WordUtils.capitalize("")          = ""
    182     * WordUtils.capitalize("i am FINE") = "I Am FINE"
    183     * </pre>
    184     *
    185     * @param str  the String to capitalize, may be null
    186     * @return capitalized String, <code>null</code> if null String input
    187     * @see #capitalizeFully(String)
    188     */
    189    public static String capitalize(final String str) {
    190        return capitalize(str, null);
    191    }
    192
    193    /**
    194     * <p>Capitalizes all the delimiter separated words in a String.
    195     * Only the first character of each word is changed. To convert the
    196     * rest of each word to lowercase at the same time,
    197     * use {@link #capitalizeFully(String, char[])}.</p>
    198     *
    199     * <p>The delimiters represent a set of characters understood to separate words.
    200     * The first string character and the first non-delimiter character after a
    201     * delimiter will be capitalized. </p>
    202     *
    203     * <p>A <code>null</code> input String returns <code>null</code>.
    204     * Capitalization uses the Unicode title case, normally equivalent to
    205     * upper case.</p>
    206     *
    207     * <pre>
    208     * WordUtils.capitalize(null, *)            = null
    209     * WordUtils.capitalize("", *)              = ""
    210     * WordUtils.capitalize(*, new char[0])     = *
    211     * WordUtils.capitalize("i am fine", null)  = "I Am Fine"
    212     * WordUtils.capitalize("i aM.fine", {'.'}) = "I aM.Fine"
    213     * </pre>
    214     *
    215     * @param str  the String to capitalize, may be null
    216     * @param delimiters  set of characters to determine capitalization, null means whitespace
    217     * @return capitalized String, <code>null</code> if null String input
    218     * @see #capitalizeFully(String)
    219     * @since 2.1
    220     */
    221    public static String capitalize(final String str, final char... delimiters) {
    222        final int delimLen = delimiters == null ? -1 : delimiters.length;
    223        if (str == null || str.isEmpty() || delimLen == 0) {
    224            return str;
    225        }
    226        final char[] buffer = str.toCharArray();
    227        boolean capitalizeNext = true;
    228        for (int i = 0; i < buffer.length; i++) {
    229            final char ch = buffer[i];
    230            if (isDelimiter(ch, delimiters)) {
    231                capitalizeNext = true;
    232            } else if (capitalizeNext) {
    233                buffer[i] = Character.toTitleCase(ch);
    234                capitalizeNext = false;
    235            }
    236        }
    237        return new String(buffer);
    238    }
    239    //-----------------------------------------------------------------------
    240    /**
    241     * Is the character a delimiter.
    242     *
    243     * @param ch  the character to check
    244     * @param delimiters  the delimiters
    245     * @return true if it is a delimiter
    246     */
    247    public static boolean isDelimiter(final char ch, final char[] delimiters) {
    248        if (delimiters == null) {
    249            return Character.isWhitespace(ch);
    250        }
    251        for (final char delimiter : delimiters) {
    252            if (ch == delimiter) {
    253                return true;
    254            }
    255        }
    256        return false;
    257    }
    258
    259    // Joining
    260    //-----------------------------------------------------------------------
    261    /**
    262     * <p>Joins the elements of the provided array into a single String
    263     * containing the provided list of elements.</p>
    264     *
    265     * <p>No separator is added to the joined String.
    266     * Null objects or empty strings within the array are represented by
    267     * empty strings.</p>
    268     *
    269     * <pre>
    270     * StringUtils.join(null)            = null
    271     * StringUtils.join([])              = ""
    272     * StringUtils.join([null])          = ""
    273     * StringUtils.join(["a", "b", "c"]) = "abc"
    274     * StringUtils.join([null, "", "a"]) = "a"
    275     * </pre>
    276     *
    277     * @param <T> the specific type of values to join together
    278     * @param elements  the values to join together, may be null
    279     * @return the joined String, {@code null} if null array input
    280     * @since 2.0
    281     * @since 3.0 Changed signature to use varargs
    282     */
    283    @SafeVarargs
    284    public static <T> String join(final T... elements) {
    285        return join(elements, null);
    286    }
    287
    288    /**
    289     * <p>Joins the elements of the provided array into a single String
    290     * containing the provided list of elements.</p>
    291     *
    292     * <p>No delimiter is added before or after the list.
    293     * Null objects or empty strings within the array are represented by
    294     * empty strings.</p>
    295     *
    296     * <pre>
    297     * StringUtils.join(null, *)               = null
    298     * StringUtils.join([], *)                 = ""
    299     * StringUtils.join([null], *)             = ""
    300     * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
    301     * StringUtils.join(["a", "b", "c"], null) = "abc"
    302     * StringUtils.join([null, "", "a"], ';')  = ";;a"
    303     * </pre>
    304     *
    305     * @param array  the array of values to join together, may be null
    306     * @param separator  the separator character to use
    307     * @return the joined String, {@code null} if null array input
    308     * @since 2.0
    309     */
    310    public static String join(final Object[] array, final char separator) {
    311        if (array == null) {
    312            return null;
    313        }
    314        return join(array, separator, 0, array.length);
    315    }
    316
    317    /**
    318     * <p>
    319     * Joins the elements of the provided array into a single String containing the provided list of elements.
    320     * </p>
    321     *
    322     * <p>
    323     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    324     * by empty strings.
    325     * </p>
    326     *
    327     * <pre>
    328     * StringUtils.join(null, *)               = null
    329     * StringUtils.join([], *)                 = ""
    330     * StringUtils.join([null], *)             = ""
    331     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    332     * StringUtils.join([1, 2, 3], null) = "123"
    333     * </pre>
    334     *
    335     * @param array
    336     *            the array of values to join together, may be null
    337     * @param separator
    338     *            the separator character to use
    339     * @return the joined String, {@code null} if null array input
    340     * @since 3.2
    341     */
    342    public static String join(final long[] array, final char separator) {
    343        if (array == null) {
    344            return null;
    345        }
    346        return join(array, separator, 0, array.length);
    347    }
    348
    349    /**
    350     * <p>
    351     * Joins the elements of the provided array into a single String containing the provided list of elements.
    352     * </p>
    353     *
    354     * <p>
    355     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    356     * by empty strings.
    357     * </p>
    358     *
    359     * <pre>
    360     * StringUtils.join(null, *)               = null
    361     * StringUtils.join([], *)                 = ""
    362     * StringUtils.join([null], *)             = ""
    363     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    364     * StringUtils.join([1, 2, 3], null) = "123"
    365     * </pre>
    366     *
    367     * @param array
    368     *            the array of values to join together, may be null
    369     * @param separator
    370     *            the separator character to use
    371     * @return the joined String, {@code null} if null array input
    372     * @since 3.2
    373     */
    374    public static String join(final int[] array, final char separator) {
    375        if (array == null) {
    376            return null;
    377        }
    378        return join(array, separator, 0, array.length);
    379    }
    380
    381    /**
    382     * <p>
    383     * Joins the elements of the provided array into a single String containing the provided list of elements.
    384     * </p>
    385     *
    386     * <p>
    387     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    388     * by empty strings.
    389     * </p>
    390     *
    391     * <pre>
    392     * StringUtils.join(null, *)               = null
    393     * StringUtils.join([], *)                 = ""
    394     * StringUtils.join([null], *)             = ""
    395     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    396     * StringUtils.join([1, 2, 3], null) = "123"
    397     * </pre>
    398     *
    399     * @param array
    400     *            the array of values to join together, may be null
    401     * @param separator
    402     *            the separator character to use
    403     * @return the joined String, {@code null} if null array input
    404     * @since 3.2
    405     */
    406    public static String join(final short[] array, final char separator) {
    407        if (array == null) {
    408            return null;
    409        }
    410        return join(array, separator, 0, array.length);
    411    }
    412
    413    /**
    414     * <p>
    415     * Joins the elements of the provided array into a single String containing the provided list of elements.
    416     * </p>
    417     *
    418     * <p>
    419     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    420     * by empty strings.
    421     * </p>
    422     *
    423     * <pre>
    424     * StringUtils.join(null, *)               = null
    425     * StringUtils.join([], *)                 = ""
    426     * StringUtils.join([null], *)             = ""
    427     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    428     * StringUtils.join([1, 2, 3], null) = "123"
    429     * </pre>
    430     *
    431     * @param array
    432     *            the array of values to join together, may be null
    433     * @param separator
    434     *            the separator character to use
    435     * @return the joined String, {@code null} if null array input
    436     * @since 3.2
    437     */
    438    public static String join(final byte[] array, final char separator) {
    439        if (array == null) {
    440            return null;
    441        }
    442        return join(array, separator, 0, array.length);
    443    }
    444
    445    /**
    446     * <p>
    447     * Joins the elements of the provided array into a single String containing the provided list of elements.
    448     * </p>
    449     *
    450     * <p>
    451     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    452     * by empty strings.
    453     * </p>
    454     *
    455     * <pre>
    456     * StringUtils.join(null, *)               = null
    457     * StringUtils.join([], *)                 = ""
    458     * StringUtils.join([null], *)             = ""
    459     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    460     * StringUtils.join([1, 2, 3], null) = "123"
    461     * </pre>
    462     *
    463     * @param array
    464     *            the array of values to join together, may be null
    465     * @param separator
    466     *            the separator character to use
    467     * @return the joined String, {@code null} if null array input
    468     * @since 3.2
    469     */
    470    public static String join(final char[] array, final char separator) {
    471        if (array == null) {
    472            return null;
    473        }
    474        return join(array, separator, 0, array.length);
    475    }
    476
    477    /**
    478     * <p>
    479     * Joins the elements of the provided array into a single String containing the provided list of elements.
    480     * </p>
    481     *
    482     * <p>
    483     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    484     * by empty strings.
    485     * </p>
    486     *
    487     * <pre>
    488     * StringUtils.join(null, *)               = null
    489     * StringUtils.join([], *)                 = ""
    490     * StringUtils.join([null], *)             = ""
    491     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    492     * StringUtils.join([1, 2, 3], null) = "123"
    493     * </pre>
    494     *
    495     * @param array
    496     *            the array of values to join together, may be null
    497     * @param separator
    498     *            the separator character to use
    499     * @return the joined String, {@code null} if null array input
    500     * @since 3.2
    501     */
    502    public static String join(final float[] array, final char separator) {
    503        if (array == null) {
    504            return null;
    505        }
    506        return join(array, separator, 0, array.length);
    507    }
    508
    509    /**
    510     * <p>
    511     * Joins the elements of the provided array into a single String containing the provided list of elements.
    512     * </p>
    513     *
    514     * <p>
    515     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    516     * by empty strings.
    517     * </p>
    518     *
    519     * <pre>
    520     * StringUtils.join(null, *)               = null
    521     * StringUtils.join([], *)                 = ""
    522     * StringUtils.join([null], *)             = ""
    523     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    524     * StringUtils.join([1, 2, 3], null) = "123"
    525     * </pre>
    526     *
    527     * @param array
    528     *            the array of values to join together, may be null
    529     * @param separator
    530     *            the separator character to use
    531     * @return the joined String, {@code null} if null array input
    532     * @since 3.2
    533     */
    534    public static String join(final double[] array, final char separator) {
    535        if (array == null) {
    536            return null;
    537        }
    538        return join(array, separator, 0, array.length);
    539    }
    540
    541
    542    /**
    543     * <p>Joins the elements of the provided array into a single String
    544     * containing the provided list of elements.</p>
    545     *
    546     * <p>No delimiter is added before or after the list.
    547     * Null objects or empty strings within the array are represented by
    548     * empty strings.</p>
    549     *
    550     * <pre>
    551     * StringUtils.join(null, *)               = null
    552     * StringUtils.join([], *)                 = ""
    553     * StringUtils.join([null], *)             = ""
    554     * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
    555     * StringUtils.join(["a", "b", "c"], null) = "abc"
    556     * StringUtils.join([null, "", "a"], ';')  = ";;a"
    557     * </pre>
    558     *
    559     * @param array  the array of values to join together, may be null
    560     * @param separator  the separator character to use
    561     * @param startIndex the first index to start joining from.  It is
    562     * an error to pass in an end index past the end of the array
    563     * @param endIndex the index to stop joining from (exclusive). It is
    564     * an error to pass in an end index past the end of the array
    565     * @return the joined String, {@code null} if null array input
    566     * @since 2.0
    567     */
    568    public static String join(final Object[] array, final char separator, final int startIndex, final int endIndex) {
    569        if (array == null) {
    570            return null;
    571        }
    572        final int noOfItems = endIndex - startIndex;
    573        if (noOfItems <= 0) {
    574            return EMPTY;
    575        }
    576        final StringBuilder buf = new StringBuilder(noOfItems * 16);
    577        for (int i = startIndex; i < endIndex; i++) {
    578            if (i > startIndex) {
    579                buf.append(separator);
    580            }
    581            if (array[i] != null) {
    582                buf.append(array[i]);
    583            }
    584        }
    585        return buf.toString();
    586    }
    587
    588    /**
    589     * <p>
    590     * Joins the elements of the provided array into a single String containing the provided list of elements.
    591     * </p>
    592     *
    593     * <p>
    594     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    595     * by empty strings.
    596     * </p>
    597     *
    598     * <pre>
    599     * StringUtils.join(null, *)               = null
    600     * StringUtils.join([], *)                 = ""
    601     * StringUtils.join([null], *)             = ""
    602     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    603     * StringUtils.join([1, 2, 3], null) = "123"
    604     * </pre>
    605     *
    606     * @param array
    607     *            the array of values to join together, may be null
    608     * @param separator
    609     *            the separator character to use
    610     * @param startIndex
    611     *            the first index to start joining from. It is an error to pass in an end index past the end of the
    612     *            array
    613     * @param endIndex
    614     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
    615     *            the array
    616     * @return the joined String, {@code null} if null array input
    617     * @since 3.2
    618     */
    619    public static String join(final long[] array, final char separator, final int startIndex, final int endIndex) {
    620        if (array == null) {
    621            return null;
    622        }
    623        final int noOfItems = endIndex - startIndex;
    624        if (noOfItems <= 0) {
    625            return EMPTY;
    626        }
    627        final StringBuilder buf = new StringBuilder(noOfItems * 16);
    628        for (int i = startIndex; i < endIndex; i++) {
    629            if (i > startIndex) {
    630                buf.append(separator);
    631            }
    632            buf.append(array[i]);
    633        }
    634        return buf.toString();
    635    }
    636
    637    /**
    638     * <p>
    639     * Joins the elements of the provided array into a single String containing the provided list of elements.
    640     * </p>
    641     *
    642     * <p>
    643     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    644     * by empty strings.
    645     * </p>
    646     *
    647     * <pre>
    648     * StringUtils.join(null, *)               = null
    649     * StringUtils.join([], *)                 = ""
    650     * StringUtils.join([null], *)             = ""
    651     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    652     * StringUtils.join([1, 2, 3], null) = "123"
    653     * </pre>
    654     *
    655     * @param array
    656     *            the array of values to join together, may be null
    657     * @param separator
    658     *            the separator character to use
    659     * @param startIndex
    660     *            the first index to start joining from. It is an error to pass in an end index past the end of the
    661     *            array
    662     * @param endIndex
    663     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
    664     *            the array
    665     * @return the joined String, {@code null} if null array input
    666     * @since 3.2
    667     */
    668    public static String join(final int[] array, final char separator, final int startIndex, final int endIndex) {
    669        if (array == null) {
    670            return null;
    671        }
    672        final int noOfItems = endIndex - startIndex;
    673        if (noOfItems <= 0) {
    674            return EMPTY;
    675        }
    676        final StringBuilder buf = new StringBuilder(noOfItems * 16);
    677        for (int i = startIndex; i < endIndex; i++) {
    678            if (i > startIndex) {
    679                buf.append(separator);
    680            }
    681            buf.append(array[i]);
    682        }
    683        return buf.toString();
    684    }
    685
    686    /**
    687     * <p>
    688     * Joins the elements of the provided array into a single String containing the provided list of elements.
    689     * </p>
    690     *
    691     * <p>
    692     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    693     * by empty strings.
    694     * </p>
    695     *
    696     * <pre>
    697     * StringUtils.join(null, *)               = null
    698     * StringUtils.join([], *)                 = ""
    699     * StringUtils.join([null], *)             = ""
    700     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    701     * StringUtils.join([1, 2, 3], null) = "123"
    702     * </pre>
    703     *
    704     * @param array
    705     *            the array of values to join together, may be null
    706     * @param separator
    707     *            the separator character to use
    708     * @param startIndex
    709     *            the first index to start joining from. It is an error to pass in an end index past the end of the
    710     *            array
    711     * @param endIndex
    712     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
    713     *            the array
    714     * @return the joined String, {@code null} if null array input
    715     * @since 3.2
    716     */
    717    public static String join(final byte[] array, final char separator, final int startIndex, final int endIndex) {
    718        if (array == null) {
    719            return null;
    720        }
    721        final int noOfItems = endIndex - startIndex;
    722        if (noOfItems <= 0) {
    723            return EMPTY;
    724        }
    725        final StringBuilder buf = new StringBuilder(noOfItems * 16);
    726        for (int i = startIndex; i < endIndex; i++) {
    727            if (i > startIndex) {
    728                buf.append(separator);
    729            }
    730            buf.append(array[i]);
    731        }
    732        return buf.toString();
    733    }
    734
    735    /**
    736     * <p>
    737     * Joins the elements of the provided array into a single String containing the provided list of elements.
    738     * </p>
    739     *
    740     * <p>
    741     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    742     * by empty strings.
    743     * </p>
    744     *
    745     * <pre>
    746     * StringUtils.join(null, *)               = null
    747     * StringUtils.join([], *)                 = ""
    748     * StringUtils.join([null], *)             = ""
    749     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    750     * StringUtils.join([1, 2, 3], null) = "123"
    751     * </pre>
    752     *
    753     * @param array
    754     *            the array of values to join together, may be null
    755     * @param separator
    756     *            the separator character to use
    757     * @param startIndex
    758     *            the first index to start joining from. It is an error to pass in an end index past the end of the
    759     *            array
    760     * @param endIndex
    761     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
    762     *            the array
    763     * @return the joined String, {@code null} if null array input
    764     * @since 3.2
    765     */
    766    public static String join(final short[] array, final char separator, final int startIndex, final int endIndex) {
    767        if (array == null) {
    768            return null;
    769        }
    770        final int noOfItems = endIndex - startIndex;
    771        if (noOfItems <= 0) {
    772            return EMPTY;
    773        }
    774        final StringBuilder buf = new StringBuilder(noOfItems * 16);
    775        for (int i = startIndex; i < endIndex; i++) {
    776            if (i > startIndex) {
    777                buf.append(separator);
    778            }
    779            buf.append(array[i]);
    780        }
    781        return buf.toString();
    782    }
    783
    784    /**
    785     * <p>
    786     * Joins the elements of the provided array into a single String containing the provided list of elements.
    787     * </p>
    788     *
    789     * <p>
    790     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    791     * by empty strings.
    792     * </p>
    793     *
    794     * <pre>
    795     * StringUtils.join(null, *)               = null
    796     * StringUtils.join([], *)                 = ""
    797     * StringUtils.join([null], *)             = ""
    798     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    799     * StringUtils.join([1, 2, 3], null) = "123"
    800     * </pre>
    801     *
    802     * @param array
    803     *            the array of values to join together, may be null
    804     * @param separator
    805     *            the separator character to use
    806     * @param startIndex
    807     *            the first index to start joining from. It is an error to pass in an end index past the end of the
    808     *            array
    809     * @param endIndex
    810     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
    811     *            the array
    812     * @return the joined String, {@code null} if null array input
    813     * @since 3.2
    814     */
    815    public static String join(final char[] array, final char separator, final int startIndex, final int endIndex) {
    816        if (array == null) {
    817            return null;
    818        }
    819        final int noOfItems = endIndex - startIndex;
    820        if (noOfItems <= 0) {
    821            return EMPTY;
    822        }
    823        final StringBuilder buf = new StringBuilder(noOfItems * 16);
    824        for (int i = startIndex; i < endIndex; i++) {
    825            if (i > startIndex) {
    826                buf.append(separator);
    827            }
    828            buf.append(array[i]);
    829        }
    830        return buf.toString();
    831    }
    832
    833    /**
    834     * <p>
    835     * Joins the elements of the provided array into a single String containing the provided list of elements.
    836     * </p>
    837     *
    838     * <p>
    839     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    840     * by empty strings.
    841     * </p>
    842     *
    843     * <pre>
    844     * StringUtils.join(null, *)               = null
    845     * StringUtils.join([], *)                 = ""
    846     * StringUtils.join([null], *)             = ""
    847     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    848     * StringUtils.join([1, 2, 3], null) = "123"
    849     * </pre>
    850     *
    851     * @param array
    852     *            the array of values to join together, may be null
    853     * @param separator
    854     *            the separator character to use
    855     * @param startIndex
    856     *            the first index to start joining from. It is an error to pass in an end index past the end of the
    857     *            array
    858     * @param endIndex
    859     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
    860     *            the array
    861     * @return the joined String, {@code null} if null array input
    862     * @since 3.2
    863     */
    864    public static String join(final double[] array, final char separator, final int startIndex, final int endIndex) {
    865        if (array == null) {
    866            return null;
    867        }
    868        final int noOfItems = endIndex - startIndex;
    869        if (noOfItems <= 0) {
    870            return EMPTY;
    871        }
    872        final StringBuilder buf = new StringBuilder(noOfItems * 16);
    873        for (int i = startIndex; i < endIndex; i++) {
    874            if (i > startIndex) {
    875                buf.append(separator);
    876            }
    877            buf.append(array[i]);
    878        }
    879        return buf.toString();
    880    }
    881
    882    /**
    883     * <p>
    884     * Joins the elements of the provided array into a single String containing the provided list of elements.
    885     * </p>
    886     *
    887     * <p>
    888     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    889     * by empty strings.
    890     * </p>
    891     *
    892     * <pre>
    893     * StringUtils.join(null, *)               = null
    894     * StringUtils.join([], *)                 = ""
    895     * StringUtils.join([null], *)             = ""
    896     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    897     * StringUtils.join([1, 2, 3], null) = "123"
    898     * </pre>
    899     *
    900     * @param array
    901     *            the array of values to join together, may be null
    902     * @param separator
    903     *            the separator character to use
    904     * @param startIndex
    905     *            the first index to start joining from. It is an error to pass in an end index past the end of the
    906     *            array
    907     * @param endIndex
    908     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
    909     *            the array
    910     * @return the joined String, {@code null} if null array input
    911     * @since 3.2
    912     */
    913    public static String join(final float[] array, final char separator, final int startIndex, final int endIndex) {
    914        if (array == null) {
    915            return null;
    916        }
    917        final int noOfItems = endIndex - startIndex;
    918        if (noOfItems <= 0) {
    919            return EMPTY;
    920        }
    921        final StringBuilder buf = new StringBuilder(noOfItems * 16);
    922        for (int i = startIndex; i < endIndex; i++) {
    923            if (i > startIndex) {
    924                buf.append(separator);
    925            }
    926            buf.append(array[i]);
    927        }
    928        return buf.toString();
    929    }
    930
    931
    932    /**
    933     * <p>Joins the elements of the provided array into a single String
    934     * containing the provided list of elements.</p>
    935     *
    936     * <p>No delimiter is added before or after the list.
    937     * A {@code null} separator is the same as an empty String ("").
    938     * Null objects or empty strings within the array are represented by
    939     * empty strings.</p>
    940     *
    941     * <pre>
    942     * StringUtils.join(null, *)                = null
    943     * StringUtils.join([], *)                  = ""
    944     * StringUtils.join([null], *)              = ""
    945     * StringUtils.join(["a", "b", "c"], "--")  = "a--b--c"
    946     * StringUtils.join(["a", "b", "c"], null)  = "abc"
    947     * StringUtils.join(["a", "b", "c"], "")    = "abc"
    948     * StringUtils.join([null, "", "a"], ',')   = ",,a"
    949     * </pre>
    950     *
    951     * @param array  the array of values to join together, may be null
    952     * @param separator  the separator character to use, null treated as ""
    953     * @return the joined String, {@code null} if null array input
    954     */
    955    public static String join(final Object[] array, final String separator) {
    956        if (array == null) {
    957            return null;
    958        }
    959        return join(array, separator, 0, array.length);
    960    }
    961
    962    /**
    963     * <p>Joins the elements of the provided array into a single String
    964     * containing the provided list of elements.</p>
    965     *
    966     * <p>No delimiter is added before or after the list.
    967     * A {@code null} separator is the same as an empty String ("").
    968     * Null objects or empty strings within the array are represented by
    969     * empty strings.</p>
    970     *
    971     * <pre>
    972     * StringUtils.join(null, *, *, *)                = null
    973     * StringUtils.join([], *, *, *)                  = ""
    974     * StringUtils.join([null], *, *, *)              = ""
    975     * StringUtils.join(["a", "b", "c"], "--", 0, 3)  = "a--b--c"
    976     * StringUtils.join(["a", "b", "c"], "--", 1, 3)  = "b--c"
    977     * StringUtils.join(["a", "b", "c"], "--", 2, 3)  = "c"
    978     * StringUtils.join(["a", "b", "c"], "--", 2, 2)  = ""
    979     * StringUtils.join(["a", "b", "c"], null, 0, 3)  = "abc"
    980     * StringUtils.join(["a", "b", "c"], "", 0, 3)    = "abc"
    981     * StringUtils.join([null, "", "a"], ',', 0, 3)   = ",,a"
    982     * </pre>
    983     *
    984     * @param array  the array of values to join together, may be null
    985     * @param separator  the separator character to use, null treated as ""
    986     * @param startIndex the first index to start joining from.
    987     * @param endIndex the index to stop joining from (exclusive).
    988     * @return the joined String, {@code null} if null array input; or the empty string
    989     * if {@code endIndex - startIndex <= 0}. The number of joined entries is given by
    990     * {@code endIndex - startIndex}
    991     * @throws ArrayIndexOutOfBoundsException ife<br>
    992     * {@code startIndex < 0} or <br>
    993     * {@code startIndex >= array.length()} or <br>
    994     * {@code endIndex < 0} or <br>
    995     * {@code endIndex > array.length()}
    996     */
    997    public static String join(final Object[] array, String separator, final int startIndex, final int endIndex) {
    998        if (array == null) {
    999            return null;
    1000        }
    1001        if (separator == null) {
    1002            separator = EMPTY;
    1003        }
    1004
    1005        // endIndex - startIndex > 0:   Len = NofStrings *(len(firstString) + len(separator))
    1006        //           (Assuming that all Strings are roughly equally long)
    1007        final int noOfItems = endIndex - startIndex;
    1008        if (noOfItems <= 0) {
    1009            return EMPTY;
    1010        }
    1011
    1012        final StringBuilder buf = new StringBuilder(noOfItems * 16);
    1013
    1014        for (int i = startIndex; i < endIndex; i++) {
    1015            if (i > startIndex) {
    1016                buf.append(separator);
    1017            }
    1018            if (array[i] != null) {
    1019                buf.append(array[i]);
    1020            }
    1021        }
    1022        return buf.toString();
    1023    }
    1024
    1025    /**
    1026     * <p>Joins the elements of the provided {@code Iterator} into
    1027     * a single String containing the provided elements.</p>
    1028     *
    1029     * <p>No delimiter is added before or after the list. Null objects or empty
    1030     * strings within the iteration are represented by empty strings.</p>
    1031     *
    1032     * <p>See the examples here: {@link #join(Object[],char)}. </p>
    1033     *
    1034     * @param iterator  the {@code Iterator} of values to join together, may be null
    1035     * @param separator  the separator character to use
    1036     * @return the joined String, {@code null} if null iterator input
    1037     * @since 2.0
    1038     */
    1039    public static String join(final Iterator<?> iterator, final char separator) {
    1040
    1041        // handle null, zero and one elements before building a buffer
    1042        if (iterator == null) {
    1043            return null;
    1044        }
    1045        if (!iterator.hasNext()) {
    1046            return EMPTY;
    1047        }
    1048        final Object first = iterator.next();
    1049        if (!iterator.hasNext()) {
    1050            final String result = first != null ? first.toString() : "";
    1051            return result;
    1052        }
    1053
    1054        // two or more elements
    1055        final StringBuilder buf = new StringBuilder(256); // Java default is 16, probably too small
    1056        if (first != null) {
    1057            buf.append(first);
    1058        }
    1059
    1060        while (iterator.hasNext()) {
    1061            buf.append(separator);
    1062            final Object obj = iterator.next();
    1063            if (obj != null) {
    1064                buf.append(obj);
    1065            }
    1066        }
    1067
    1068        return buf.toString();
    1069    }
    1070
    1071    /**
    1072     * <p>Joins the elements of the provided {@code Iterator} into
    1073     * a single String containing the provided elements.</p>
    1074     *
    1075     * <p>No delimiter is added before or after the list.
    1076     * A {@code null} separator is the same as an empty String ("").</p>
    1077     *
    1078     * <p>See the examples here: {@link #join(Object[],String)}. </p>
    1079     *
    1080     * @param iterator  the {@code Iterator} of values to join together, may be null
    1081     * @param separator  the separator character to use, null treated as ""
    1082     * @return the joined String, {@code null} if null iterator input
    1083     */
    1084    public static String join(final Iterator<?> iterator, final String separator) {
    1085
    1086        // handle null, zero and one elements before building a buffer
    1087        if (iterator == null) {
    1088            return null;
    1089        }
    1090        if (!iterator.hasNext()) {
    1091            return EMPTY;
    1092        }
    1093        final Object first = iterator.next();
    1094        if (!iterator.hasNext()) {
    1095            final String result = first != null ? first.toString() : "";
    1096            return result;
    1097        }
    1098
    1099        // two or more elements
    1100        final StringBuilder buf = new StringBuilder(256); // Java default is 16, probably too small
    1101        if (first != null) {
    1102            buf.append(first);
    1103        }
    1104
    1105        while (iterator.hasNext()) {
    1106            if (separator != null) {
    1107                buf.append(separator);
    1108            }
    1109            final Object obj = iterator.next();
    1110            if (obj != null) {
    1111                buf.append(obj);
    1112            }
    1113        }
    1114        return buf.toString();
    1115    }
    1116
    1117    /**
    1118     * <p>Joins the elements of the provided {@code Iterable} into
    1119     * a single String containing the provided elements.</p>
    1120     *
    1121     * <p>No delimiter is added before or after the list. Null objects or empty
    1122     * strings within the iteration are represented by empty strings.</p>
    1123     *
    1124     * <p>See the examples here: {@link #join(Object[],char)}. </p>
    1125     *
    1126     * @param iterable  the {@code Iterable} providing the values to join together, may be null
    1127     * @param separator  the separator character to use
    1128     * @return the joined String, {@code null} if null iterator input
    1129     * @since 2.3
    1130     */
    1131    public static String join(final Iterable<?> iterable, final char separator) {
    1132        if (iterable == null) {
    1133            return null;
    1134        }
    1135        return join(iterable.iterator(), separator);
    1136    }
    1137
    1138    /**
    1139     * <p>Joins the elements of the provided {@code Iterable} into
    1140     * a single String containing the provided elements.</p>
    1141     *
    1142     * <p>No delimiter is added before or after the list.
    1143     * A {@code null} separator is the same as an empty String ("").</p>
    1144     *
    1145     * <p>See the examples here: {@link #join(Object[],String)}. </p>
    1146     *
    1147     * @param iterable  the {@code Iterable} providing the values to join together, may be null
    1148     * @param separator  the separator character to use, null treated as ""
    1149     * @return the joined String, {@code null} if null iterator input
    1150     * @since 2.3
    1151     */
    1152    public static String join(final Iterable<?> iterable, final String separator) {
    1153        if (iterable == null) {
    1154            return null;
    1155        }
    1156        return join(iterable.iterator(), separator);
    1157    }
    1158
    1159
    1160    /**
    1161     * <p>Checks if the CharSequence contains only Unicode digits.
    1162     * A decimal point is not a Unicode digit and returns false.</p>
    1163     *
    1164     * <p>{@code null} will return {@code false}.
    1165     * An empty CharSequence (length()=0) will return {@code false}.</p>
    1166     *
    1167     * <p>Note that the method does not allow for a leading sign, either positive or negative.
    1168     * Also, if a String passes the numeric test, it may still generate a NumberFormatException
    1169     * when parsed by Integer.parseInt or Long.parseLong, e.g. if the value is outside the range
    1170     * for int or long respectively.</p>
    1171     *
    1172     * <pre>
    1173     * StringUtils.isNumeric(null)   = false
    1174     * StringUtils.isNumeric("")     = false
    1175     * StringUtils.isNumeric("  ")   = false
    1176     * StringUtils.isNumeric("123")  = true
    1177     * StringUtils.isNumeric("\u0967\u0968\u0969")  = true
    1178     * StringUtils.isNumeric("12 3") = false
    1179     * StringUtils.isNumeric("ab2c") = false
    1180     * StringUtils.isNumeric("12-3") = false
    1181     * StringUtils.isNumeric("12.3") = false
    1182     * StringUtils.isNumeric("-123") = false
    1183     * StringUtils.isNumeric("+123") = false
    1184     * </pre>
    1185     *
    1186     * @param cs  the CharSequence to check, may be null
    1187     * @return {@code true} if only contains digits, and is non-null
    1188     * @since 3.0 Changed signature from isNumeric(String) to isNumeric(CharSequence)
    1189     * @since 3.0 Changed "" to return false and not true
    1190     */
    1191    public static boolean isNumeric(final CharSequence cs) {
    1192        if (cs == null || cs.length() == 0) {
    1193            return false;
    1194        }
    1195        final int sz = cs.length();
    1196        for (int i = 0; i < sz; i++) {
    1197            if (!Character.isDigit(cs.charAt(i))) {
    1198                return false;
    1199            }
    1200        }
    1201        return true;
    1202    }
    1203
    1204
    1205    // startsWith
    1206    //-----------------------------------------------------------------------
    1207
    1208    /**
    1209     * <p>Check if a CharSequence starts with a specified prefix.</p>
    1210     *
    1211     * <p>{@code null}s are handled without exceptions. Two {@code null}
    1212     * references are considered to be equal. The comparison is case sensitive.</p>
    1213     *
    1214     * <pre>
    1215     * StringUtils.startsWith(null, null)      = true
    1216     * StringUtils.startsWith(null, "abc")     = false
    1217     * StringUtils.startsWith("abcdef", null)  = false
    1218     * StringUtils.startsWith("abcdef", "abc") = true
    1219     * StringUtils.startsWith("ABCDEF", "abc") = false
    1220     * </pre>
    1221     *
    1222     * @see java.lang.String#startsWith(String)
    1223     * @param str  the CharSequence to check, may be null
    1224     * @param prefix the prefix to find, may be null
    1225     * @return {@code true} if the CharSequence starts with the prefix, case sensitive, or
    1226     *  both {@code null}
    1227     * @since 2.4
    1228     * @since 3.0 Changed signature from startsWith(String, String) to startsWith(CharSequence, CharSequence)
    1229     */
    1230    public static boolean startsWith(final CharSequence str, final CharSequence prefix) {
    1231        return startsWith(str, prefix, false);
    1232    }
    1233
    1234    /**
    1235     * <p>Case insensitive check if a CharSequence starts with a specified prefix.</p>
    1236     *
    1237     * <p>{@code null}s are handled without exceptions. Two {@code null}
    1238     * references are considered to be equal. The comparison is case insensitive.</p>
    1239     *
    1240     * <pre>
    1241     * StringUtils.startsWithIgnoreCase(null, null)      = true
    1242     * StringUtils.startsWithIgnoreCase(null, "abc")     = false
    1243     * StringUtils.startsWithIgnoreCase("abcdef", null)  = false
    1244     * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true
    1245     * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true
    1246     * </pre>
    1247     *
    1248     * @see java.lang.String#startsWith(String)
    1249     * @param str  the CharSequence to check, may be null
    1250     * @param prefix the prefix to find, may be null
    1251     * @return {@code true} if the CharSequence starts with the prefix, case insensitive, or
    1252     *  both {@code null}
    1253     * @since 2.4
    1254     * @since 3.0 Changed signature from startsWithIgnoreCase(String, String) to startsWithIgnoreCase(CharSequence, CharSequence)
    1255     */
    1256    public static boolean startsWithIgnoreCase(final CharSequence str, final CharSequence prefix) {
    1257        return startsWith(str, prefix, true);
    1258    }
    1259
    1260    /**
    1261     * <p>Check if a CharSequence starts with a specified prefix (optionally case insensitive).</p>
    1262     *
    1263     * @see java.lang.String#startsWith(String)
    1264     * @param str  the CharSequence to check, may be null
    1265     * @param prefix the prefix to find, may be null
    1266     * @param ignoreCase indicates whether the compare should ignore case
    1267     *  (case insensitive) or not.
    1268     * @return {@code true} if the CharSequence starts with the prefix or
    1269     *  both {@code null}
    1270     */
    1271    private static boolean startsWith(final CharSequence str, final CharSequence prefix, final boolean ignoreCase) {
    1272        if (str == null || prefix == null) {
    1273            return str == null && prefix == null;
    1274        }
    1275        if (prefix.length() > str.length()) {
    1276            return false;
    1277        }
    1278        return regionMatches(str, ignoreCase, 0, prefix, 0, prefix.length());
    1279    }
    1280
    1281    /**
    1282     * Green implementation of regionMatches.
    1283     *
    1284     * @param cs the {@code CharSequence} to be processed
    1285     * @param ignoreCase whether or not to be case insensitive
    1286     * @param thisStart the index to start on the {@code cs} CharSequence
    1287     * @param substring the {@code CharSequence} to be looked for
    1288     * @param start the index to start on the {@code substring} CharSequence
    1289     * @param length character length of the region
    1290     * @return whether the region matched
    1291     */
    1292    static boolean regionMatches(final CharSequence cs, final boolean ignoreCase, final int thisStart,
    1293                                 final CharSequence substring, final int start, final int length)    {
    1294        if (cs instanceof String && substring instanceof String) {
    1295            return ((String) cs).regionMatches(ignoreCase, thisStart, (String) substring, start, length);
    1296        }
    1297        int index1 = thisStart;
    1298        int index2 = start;
    1299        int tmpLen = length;
    1300
    1301        // Extract these first so we detect NPEs the same as the java.lang.String version
    1302        final int srcLen = cs.length() - thisStart;
    1303        final int otherLen = substring.length() - start;
    1304
    1305        // Check for invalid parameters
    1306        if (thisStart < 0 || start < 0 || length < 0) {
    1307            return false;
    1308        }
    1309
    1310        // Check that the regions are long enough
    1311        if (srcLen < length || otherLen < length) {
    1312            return false;
    1313        }
    1314
    1315        while (tmpLen-- > 0) {
    1316            final char c1 = cs.charAt(index1++);
    1317            final char c2 = substring.charAt(index2++);
    1318
    1319            if (c1 == c2) {
    1320                continue;
    1321            }
    1322
    1323            if (!ignoreCase) {
    1324                return false;
    1325            }
    1326
    1327            // The same check as in String.regionMatches():
    1328            if (Character.toUpperCase(c1) != Character.toUpperCase(c2)
    1329                    && Character.toLowerCase(c1) != Character.toLowerCase(c2)) {
    1330                return false;
    1331            }
    1332        }
    1333
    1334        return true;
    1335    }
    1336
    1337    /**
    1338     * The index value when an element is not found in a list or array: <code>-1</code>.
    1339     * This value is returned by methods in this class and can also be used in comparisons with values returned by
    1340     * various method from {@link java.util.List}.
    1341     */
    1342    public static final int INDEX_NOT_FOUND = -1;
    1343
    1344    // IndexOf search
    1345    // ----------------------------------------------------------------------
    1346
    1347    // Object IndexOf
    1348    //-----------------------------------------------------------------------
    1349    /**
    1350     * <p>Finds the index of the given object in the array.</p>
    1351     *
    1352     * <p>This method returns {@link #INDEX_NOT_FOUND} (<code>-1</code>) for a <code>null</code> input array.</p>
    1353     *
    1354     * @param array  the array to search through for the object, may be <code>null</code>
    1355     * @param objectToFind  the object to find, may be <code>null</code>
    1356     * @return the index of the object within the array,
    1357     *  {@link #INDEX_NOT_FOUND} (<code>-1</code>) if not found or <code>null</code> array input
    1358     */
    1359    public static int indexOf(Object[] array, Object objectToFind) {
    1360        return indexOf(array, objectToFind, 0);
    1361    }
    1362
    1363    /**
    1364     * <p>Finds the index of the given object in the array starting at the given index.</p>
    1365     *
    1366     * <p>This method returns {@link #INDEX_NOT_FOUND} (<code>-1</code>) for a <code>null</code> input array.</p>
    1367     *
    1368     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
    1369     * length will return {@link #INDEX_NOT_FOUND} (<code>-1</code>).</p>
    1370     *
    1371     * @param array  the array to search through for the object, may be <code>null</code>
    1372     * @param objectToFind  the object to find, may be <code>null</code>
    1373     * @param startIndex  the index to start searching at
    1374     * @return the index of the object within the array starting at the index,
    1375     *  {@link #INDEX_NOT_FOUND} (<code>-1</code>) if not found or <code>null</code> array input
    1376     */
    1377    public static int indexOf(Object[] array, Object objectToFind, int startIndex) {
    1378        if (array == null) {
    1379            return INDEX_NOT_FOUND;
    1380        }
    1381        if (startIndex < 0) {
    1382            startIndex = 0;
    1383        }
    1384        if (objectToFind == null) {
    1385            for (int i = startIndex; i < array.length; i++) {
    1386                if (array[i] == null) {
    1387                    return i;
    1388                }
    1389            }
    1390        } else {
    1391            for (int i = startIndex; i < array.length; i++) {
    1392                if (objectToFind.equals(array[i])) {
    1393                    return i;
    1394                }
    1395            }
    1396        }
    1397        return INDEX_NOT_FOUND;
    1398    }
    1399}