// /////////////////////////////////////////////////////////
// This file is part of Propel.
//
// Propel is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Propel is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Propel. If not, see <http://www.gnu.org/licenses/>.
// /////////////////////////////////////////////////////////
// Authored by: Nikolaos Tountas -> salam.kaser-at-gmail.com
// /////////////////////////////////////////////////////////
package propel.core.utils;
import static propel.core.functional.predicates.Strings.isNotNullOrEmpty;
import static propel.core.functional.predicates.Strings.lengthEquals;
import static propel.core.functional.projections.Strings.charAt;
import java.math.BigDecimal;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.text.Collator;
import java.text.DateFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
import lombok.Validate;
import lombok.Validate.NotNull;
import lombok.val;
import org.joda.time.Duration;
import org.joda.time.LocalDateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeFormatterBuilder;
import org.joda.time.format.DateTimeParser;
import org.joda.time.format.ISODateTimeFormat;
import propel.core.TryResult;
import propel.core.collections.lists.ReifiedArrayList;
import propel.core.collections.lists.ReifiedList;
import propel.core.common.CONSTANT;
import propel.core.userTypes.Int128;
import propel.core.userTypes.UnsignedByte;
import propel.core.userTypes.UnsignedInteger;
import propel.core.userTypes.UnsignedLong;
import propel.core.userTypes.UnsignedShort;
/**
* Provides helper functionality for Strings and char arrays.
*/
public final class StringUtils
{
/**
* The current locale of the JVM
*/
public static final Locale CURRENT_LOCALE = Locale.getDefault();
/**
* An invariant locale across JVMs
*/
public static final Locale INVARIANT_LOCALE = Locale.US;
/**
* The current locale's collator
*/
public static final Collator CURRENT_LOCALE_COLLATOR = Collator.getInstance(CURRENT_LOCALE);
/**
* The invariant locale's collator
*/
public static final Collator INVARIANT_LOCALE_COLLATOR = Collator.getInstance(INVARIANT_LOCALE);
private static final DecimalFormatSymbols CURRENT_DECIMAL_SYMBOLS = new DecimalFormatSymbols(CURRENT_LOCALE);
/**
* Current locale decimal separator symbol
*/
public static final char DECIMAL_SEPARATOR = CURRENT_DECIMAL_SYMBOLS.getDecimalSeparator();
/**
* Current locale decimal grouping symbol
*/
public static final char GROUPING_SEPARATOR = CURRENT_DECIMAL_SYMBOLS.getGroupingSeparator();
private static final Duration MIN_DURATION = new Duration(Long.MIN_VALUE);
private static final Duration MAX_DURATION = new Duration(Long.MAX_VALUE);
private static final LocalDateTime MIN_DATETIME = new LocalDateTime(1, 1, 1, 0, 0, 0); // 1/1/0001 00:00:00
private static final LocalDateTime MAX_DATETIME = new LocalDateTime(9999, 12, 31, 23, 59, 59); // 31/12/9999 23:59:59
/**
* ISO standard date/time formatters (composite class)
*/
public static final DateTimeFormatter STANDARD_FORMATTERS = (new DateTimeFormatterBuilder()).append(null, createCommonDateTimeParsers())
.toFormatter();
/**
* Returns a character range from start (inclusive) to end (exclusive).
*
* @throws IllegalArgumentException When the end is before start
*/
public static char[] charRange(char start, char end)
{
int length = (int) end - (int) start;
if (length < 0)
throw new IllegalArgumentException("start=" + (int) start + " end=" + (int) end);
char[] result = new char[length];
int index = 0;
for (char ch = start; ch < end; ch++)
result[index++] = ch;
return result;
}
/**
* Returns a character range from start (inclusive) to end (exclusive).
*
* @throws IllegalArgumentException When the end is before start
*/
public static char[] charRange(int start, int end)
{
return charRange((char) start, (char) end);
}
/**
* Compares two Strings using a CurrentLocale string comparison.
*
* @throws NullPointerException An argument is null.
*/
public static int compare(String a, String b)
{
return compare(a, b, StringComparison.CurrentLocale);
}
/**
* Compares two Strings using the specified string comparison.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static int compare(@NotNull final String a, @NotNull final String b, StringComparison stringComparison)
{
switch(stringComparison)
{
case CurrentLocale:
return compareLocaleSensitive(a, b, CURRENT_LOCALE, CURRENT_LOCALE_COLLATOR, true);
case CurrentLocaleIgnoreCase:
return compareLocaleSensitive(a, b, CURRENT_LOCALE, CURRENT_LOCALE_COLLATOR, false);
case InvariantLocale:
return compareLocaleSensitive(a, b, INVARIANT_LOCALE, INVARIANT_LOCALE_COLLATOR, true);
case InvariantLocaleIgnoreCase:
return compareLocaleSensitive(a, b, INVARIANT_LOCALE, INVARIANT_LOCALE_COLLATOR, false);
case Ordinal:
return compareOrdinal(a, b, true);
case OrdinalIgnoreCase:
return compareOrdinal(a, b, false);
default:
throw new IllegalArgumentException("stringComparison has an unexpected value: " + stringComparison.toString());
}
}
/**
* Comparison function, uses higher performance locale-aware comparison, uses existing collator to avoid creating one every time.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static int compare(@NotNull final String a, @NotNull final String b, Locale locale, Collator collator, boolean caseSensitive)
{
return compareLocaleSensitive(a, b, locale, collator, caseSensitive);
}
/**
* Locale-aware comparison.
*
* @throws NullPointerException An argument is null
*/
@Validate
private static int compareLocaleSensitive(String a, String b, @NotNull final Locale locale, @NotNull final Collator collator,
boolean caseSensitive)
{
if (!caseSensitive)
{
a = a.toLowerCase(locale);
b = b.toLowerCase(locale);
}
return collator.compare(a, b);
}
/**
* Compares two strings lexicographically
*
* @throws NullPointerException An argument is null
*/
private static int compareOrdinal(String a, String b, boolean caseSensitive)
{
if (caseSensitive)
return a.compareTo(b);
else
{
// ordinal ignore case
int len1 = a.length();
int len2 = b.length();
int lim = len1 < len2 ? len1 : len2;
char v1[] = a.toCharArray();
char v2[] = b.toCharArray();
int i = 0;
while (i < lim)
{
char c1 = v1[i];
char c2 = v2[i];
// letters
if ((c1 >= 65 && c1 <= 90) || (c1 >= 97 && c1 <= 122))
{
c1 = Character.toLowerCase(c1);
c2 = Character.toLowerCase(c2);
}
if (c1 != c2)
return c1 - c2;
i++;
}
return len1 - len2;
}
}
/**
* Concatenates a collection of strings into a single string. Ignores null items.
*
* @throws NullPointerException An argument is null.
*/
public static String concat(Iterable<String> values)
{
return delimit(values, CONSTANT.EMPTY_STRING, null);
}
/**
* Concatenates a collection of strings into a single string. Substitutes null items with the null-replacement value provided, if not
* null.
*
* @throws NullPointerException The values argument is null.
*/
public static String concat(Iterable<String> values, String nullReplacementValue)
{
return delimit(values, CONSTANT.EMPTY_STRING, nullReplacementValue);
}
/**
* Concatenates a collection of strings into a single string. Ignores null items.
*
* @throws NullPointerException An argument is null.
*/
public static String concat(String[] values)
{
return delimit(values, CONSTANT.EMPTY_STRING, null);
}
/**
* Concatenates a collection of strings into a single string. Substitutes null items with the null-replacement value provided, if not
* null.
*
* @throws NullPointerException The values argument is null.
*/
public static String concat(String[] values, String nullReplacementValue)
{
return delimit(values, CONSTANT.EMPTY_STRING, nullReplacementValue);
}
/**
* Concatenates the given chars. Returns String.Empty if an empty collection was provided.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static String concat(@NotNull final char[] values)
{
return new String(values);
}
/**
* Concatenates the given chars. Returns an empty array if no chars are found.
*
* @throws NullPointerException When the values or one of its arguments is null.
*/
@Validate
public static char[] concat(@NotNull final char[]... values)
{
int count = 0;
for (char[] arr : values)
{
if (arr == null)
throw new NullPointerException("Item of values");
count += arr.length;
}
char[] result = new char[count];
int index = 0;
for (char[] arr : values)
{
System.arraycopy(arr, 0, result, index, arr.length);
index += arr.length;
}
return result;
}
/**
* Returns true if a char sequence contains a character
*
* @throws NullPointerException When the sequence is null.
*/
@Validate
public static boolean contains(@NotNull final char[] sequence, char ch)
{
for (char c : sequence)
if (c == ch)
return true;
return false;
}
/**
* Returns true if a string contains a character
*
* @throws NullPointerException When the sequence is null.
*/
@Validate
public static boolean contains(@NotNull final String value, char ch)
{
for (char c : value.toCharArray())
if (c == ch)
return true;
return false;
}
/**
* Returns true if the part is contained in the value. Uses CurrentLocale string comparison.
*
* @throws NullPointerException An argument is null.
*/
public static boolean contains(String value, String part)
{
return contains(value, part, StringComparison.CurrentLocale);
}
/**
* Returns true if the part is contained in the value. Uses the specified string comparison.
*
* @throws NullPointerException An argument is null.
*/
public static boolean contains(String value, String part, StringComparison stringComparison)
{
return indexOf(value, part, 0, value.length(), stringComparison) >= 0;
}
/**
* Returns true if the part is contained in the value. Uses culture-aware higher performance string comparison.
*
* @throws NullPointerException An argument is null.
*/
public static boolean contains(String value, String part, Locale locale, Collator collator, boolean caseSensitive)
{
return indexOf(value, part, 0, value.length(), locale, collator, caseSensitive) >= 0;
}
/**
* Returns true if the value is contained in the collection of values. Uses the specified string comparison mode.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static boolean contains(@NotNull final Iterable<String> values, String value, StringComparison stringComparison)
{
if (value == null)
return Linq.contains(values, null);
else
for (String val : values)
if (equal(value, val, stringComparison))
return true;
return false;
}
/**
* Returns true if the value is contained in the collection of values. Uses culture-aware higher performance string comparison.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static boolean contains(@NotNull final Iterable<String> values, String value, Locale locale, Collator collator,
boolean caseSensitive)
{
if (value == null)
return Linq.contains(values, null);
else
for (String val : values)
if (equal(value, val, locale, collator, caseSensitive))
return true;
return false;
}
/**
* Returns true if the value is contained in the collection of values. Uses the specified string comparison mode.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static boolean contains(@NotNull final String[] values, String value, StringComparison stringComparison)
{
if (value == null)
return Linq.contains(values, null);
else
for (String val : values)
if (equal(value, val, stringComparison))
return true;
return false;
}
/**
* Returns true if the value is contained in the collection of values. Uses culture-aware higher performance string comparison.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static boolean contains(@NotNull final String[] values, String value, Locale locale, Collator collator, boolean caseSensitive)
{
if (value == null)
return Linq.contains(values, null);
else
for (String val : values)
if (equal(value, val, locale, collator, caseSensitive))
return true;
return false;
}
/**
* Returns true if all characters are contained in a string. Order is not taken into consideration.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static boolean containsAll(@NotNull final String value, @NotNull final char[] characters)
{
for (char ch : characters)
if (value.indexOf(ch) < 0)
return false;
return true;
}
/**
* Returns true if all strings specified are contained in the value string. Order is not taken into consideration. Uses the CurrentLocale
* StringComparison.
*
* @throws NullPointerException An argument is null.
*/
public static boolean containsAll(String value, Iterable<String> parts)
{
return containsAll(value, parts, StringComparison.CurrentLocale);
}
/**
* Returns true if all strings specified are contained in the value string. Order is not taken into consideration. If a part is null then
* false is returned.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static boolean containsAll(@NotNull final String value, @NotNull final Iterable<String> parts, StringComparison stringComparison)
{
// check that all exist
for (String part : parts)
if (part == null)
return false;
else if (indexOf(value, part, 0, value.length(), stringComparison) < 0)
return false;
return true;
}
/**
* Returns true if all strings specified are contained in the value string. Order is not taken into consideration. If a part is null then
* false is returned. Uses culture-aware higher performance string comparison.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static boolean containsAll(@NotNull final String value, @NotNull final Iterable<String> parts, Locale locale, Collator collator,
boolean caseSensitive)
{
// check that all exist
for (String part : parts)
if (part == null)
return false;
else if (indexOf(value, part, 0, value.length(), locale, collator, caseSensitive) < 0)
return false;
return true;
}
/**
* Returns true if all items are contained in the values string collection. Order is not taken into consideration. You may use null
* elements for both values and items. Uses CurrentLocale string comparison.
*
* @throws NullPointerException An argument is null.
*/
public static boolean containsAll(Iterable<String> values, Iterable<String> items)
{
return containsAll(values, items, StringComparison.CurrentLocale);
}
/**
* Returns true if all items are contained in the values string collection. Order is not taken into consideration. You may use null
* elements for both values and items.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static boolean containsAll(@NotNull final Iterable<String> values, @NotNull final Iterable<String> items,
StringComparison stringComparison)
{
for (String item : items)
{
boolean found = false;
for (String value : values)
{
if (item == null && value == null)
continue;
if (item == null || value == null)
return false;
if (equal(item, value, stringComparison))
found = true;
}
if (!found)
return false;
}
return true;
}
/**
* Returns true if all items in items are contained in the values string collection. Order is not taken into consideration. You may use
* null elements for values and items. Uses a culture-aware higher performance string comparison.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static boolean containsAll(@NotNull final Iterable<String> values, @NotNull final Iterable<String> items, Locale locale,
Collator collator, boolean caseSensitive)
{
for (String item : items)
{
boolean found = false;
for (String value : values)
{
if (item == null && value == null)
continue;
if (item == null || value == null)
return false;
if (equal(item, value, locale, collator, caseSensitive))
found = true;
}
if (!found)
return false;
}
return true;
}
/**
* Returns true if all characters are contained in a string. Order is not taken into consideration.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static boolean containsAny(@NotNull final String value, @NotNull final char[] characters)
{
for (char ch : characters)
if (value.indexOf(ch) >= 0)
return true;
return false;
}
/**
* Returns true if any of the strings are contained in a string. Order is not taken into consideration. Uses the CurrentLocale
* StringComparison.
*
* @throws NullPointerException An argument is null.
*/
public static boolean containsAny(String value, Iterable<String> parts)
{
return containsAny(value, parts, StringComparison.CurrentLocale);
}
/**
* Returns true if any of the strings are contained in a string. Order is not taken into consideration. If a part is null then it is
* ignored.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static boolean containsAny(@NotNull final String value, @NotNull final Iterable<String> parts, StringComparison stringComparison)
{
// check if parts contained
for (String part : parts)
if (part != null)
if (contains(value, part, stringComparison))
return true;
return false;
}
/**
* Returns true if any of the strings are contained in a string. Order is not taken into consideration. If a part is null then it is
* ignored. Uses a culture-aware higher performance string comparison.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static boolean containsAny(@NotNull final String value, @NotNull final Iterable<String> parts, Locale locale, Collator collator,
boolean caseSensitive)
{
// check if parts contained
for (String part : parts)
if (part != null)
if (contains(value, part, locale, collator, caseSensitive))
return true;
return false;
}
/**
* Returns true if any item in items is contained in the values string collection. Order is not taken into consideration. You may use null
* elements for values and items.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static boolean containsAny(@NotNull final Iterable<String> values, @NotNull final Iterable<String> items,
StringComparison stringComparison)
{
for (String item : items)
for (String value : values)
{
if (item == null && value == null)
return true;
if (item == null || value == null)
continue;
if (equal(item, value, stringComparison))
return true;
}
return false;
}
/**
* Returns true if any item in items is contained in the values string collection. Order is not taken into consideration. You may use null
* elements for values and items. Uses a culture-aware higher performance string comparison.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static boolean containsAny(@NotNull final Iterable<String> values, @NotNull final Iterable<String> items, Locale locale,
Collator collator, boolean caseSensitive)
{
for (String item : items)
for (String value : values)
{
if (item == null && value == null)
return true;
if (item == null || value == null)
continue;
if (equal(item, value, locale, collator, caseSensitive))
return true;
}
return false;
}
/**
* Similar to String.Substring
*
* @throws NullPointerException An argument is null.
* @throws IndexOutOfBoundsException An index is out of bounds.
*/
@Validate
public static String copy(@NotNull final String value, int startIndex, int endIndex)
{
if (startIndex < 0 || startIndex > endIndex)
throw new IndexOutOfBoundsException("startIndex=" + startIndex + " endIndex=" + endIndex);
if (endIndex > value.length())
throw new IndexOutOfBoundsException("endIndex=" + endIndex + " length=" + value.length());
return value.substring(startIndex, endIndex);
}
/**
* Returns the number of occurences of a character in a character array.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static int count(@NotNull final char[] array, char ch)
{
int count = 0;
for (char c : array)
if (c == ch)
count++;
return count;
}
/**
* Returns the number of occurences of a character in a string value.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static int count(@NotNull final String value, char character)
{
int result = 0;
for (char s : value.toCharArray())
if (s == character)
result++;
return result;
}
/**
* Returns the number of occurences of a string element in a string value, using the CurrentLocale StringComparison.
*
* @throws NullPointerException An argument is null.
*/
public static int count(String value, String element)
{
return count(value, element, StringComparison.CurrentLocale);
}
/**
* Returns the number of occurences of a string element in a string value, using the specified string comparison type.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static int count(@NotNull final String value, @NotNull final String element, StringComparison stringComparison)
{
int valLen = value.length();
if (valLen <= 0 || element.length() <= 0)
return 0;
int result = 0;
int index = 0;
while ((index = indexOf(value, element, index, valLen - index, stringComparison)) >= 0)
{
index++;
result++;
}
return result;
}
/**
* Returns the number of occurences of a string element in a string value, using the specified string comparison type. Uses a
* culture-aware higher performance string comparison.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static int count(@NotNull final String value, @NotNull final String element, Locale locale, Collator collator,
boolean caseSensitive)
{
int valLen = value.length();
if (valLen <= 0 || element.length() <= 0)
return 0;
int result = 0;
int index = 0;
while ((index = indexOf(value, element, index, valLen - index, locale, collator, caseSensitive)) >= 0)
{
index++;
result++;
}
return result;
}
/**
* Performs a cropStart and cropEnd, returning the result
*
* @throws NullPointerException An argument is null
*/
public static String crop(String value, char except)
{
return cropStart(cropEnd(value, except), except);
}
/**
* Performs a cropStart and cropEnd, returning the result
*
* @throws NullPointerException An argument is null
*/
public static String crop(String value, char[] except)
{
return cropStart(cropEnd(value, except), except);
}
/**
* Crops all characters from the start of the given string, until the except character is encountered
*
* @throws NullPointerException An argument is null
*/
public static String cropStart(String value, char except)
{
return cropStart(value, new char[] {except});
}
/**
* Crops all characters from the start of the given string, until a character is encountered which exists in the given exception array
*
* @throws NullPointerException An argument is null
*/
@Validate
public static String cropStart(@NotNull final String value, @NotNull final char[] except)
{
int startIndex = 0;
while (startIndex <= value.length() - 1 && !contains(except, value.charAt(startIndex)))
startIndex++;
return value.substring(startIndex);
}
/**
* Crops all characters from the end of the given string, until the except character is encountered
*
* @throws NullPointerException An argument is null
*/
public static String cropEnd(String value, char except)
{
return cropEnd(value, new char[] {except});
}
/**
* Crops all characters from the end of the given string, until a character is encountered which exists in the given exception array
*
* @throws NullPointerException An argument is null
*/
@Validate
public static String cropEnd(@NotNull final String value, @NotNull final char[] except)
{
int endIndex = value.length() - 1;
while (endIndex > 0 && !contains(except, value.charAt(endIndex)))
endIndex--;
return value.substring(0, endIndex + 1);
}
/**
* Returns CR, LF or CRLF, depending on the frequency of line separators found in the given text data.
*
* @throws NullPointerException An argument is null.
*/
public static String detectLineSeparator(String text)
{
return detectLineSeparator(text, 2.0f);
}
/**
* Returns CR, LF or CRLF, depending on the frequency of line separators found in the given text data. Accepts a ratio, to ensure the
* decision is not swayed by CRs or LFs appearing randomly in the code. For example a value of 2.0f for a CR End-Of-Line (EOL) terminated
* file would return CR if the file contains twice the number of CRs than the number of LFs.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static String detectLineSeparator(@NotNull final String text, float ratio)
{
int crs = count(text, CONSTANT.CR_CHAR);
int lfs = count(text, CONSTANT.LF_CHAR);
// multiply to ensure random CR/LFs used in source do not affect the outcome
if (crs > lfs * ratio)
return CONSTANT.CR;
else if (lfs > crs * ratio)
return CONSTANT.LF;
else
return CONSTANT.CRLF;
}
/**
* Deletes the specified range of characters from the string.
*
* @throws NullPointerException An argument is null.
* @throws IndexOutOfBoundsException An index is out of bounds.
*/
@Validate
public static String delete(@NotNull final String value, int startIndex, int endIndex)
{
if (startIndex < 0 || startIndex > endIndex)
throw new IndexOutOfBoundsException("startIndex=" + startIndex + " endIndex=" + endIndex);
if (endIndex > value.length())
throw new IndexOutOfBoundsException("endIndex=" + endIndex + " length=" + value.length());
return value.substring(0, startIndex) + value.substring(endIndex);
}
/**
* Concatenates the given values using their toString() method and appending the given delimiter between all values. Returns String.Empty
* if an empty or null collection was provided. Ignores null collection items.
*
* @throws NullPointerException An argument is null.
*/
public static String delimit(Iterable<String> values, String delimiter)
{
return delimit(values, delimiter, null);
}
/**
* Concatenates the given values using their toString() method and appending the given delimiter between all values. Returns String.Empty
* if an empty or null collection was provided. Substitutes null items with a null-replacement value, if provided and is not null.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static String delimit(@NotNull final Iterable<String> values, @NotNull final String delimiter, String nullReplacementValue)
{
val sb = new StringBuilder(256);
for (String value : values)
if (value != null)
{
sb.append(value.toString());
sb.append(delimiter);
} else
// append null replacement
if (nullReplacementValue != null)
{
sb.append(nullReplacementValue);
sb.append(delimiter);
}
if (sb.length() > 0)
return sb.subSequence(0, sb.length() - delimiter.length()).toString();
return CONSTANT.EMPTY_STRING;
}
/**
* Concatenates the given values using their toString() method and appending the given delimiter between all values. Returns String.Empty
* if an empty or null collection was provided. Ignores null collection items.
*
* @throws NullPointerException An argument is null.
*/
public static String delimit(String[] values, String delimiter)
{
return delimit(values, delimiter, null);
}
/**
* Concatenates the given values using their toString() method and appending the given delimiter between all values. Returns String.Empty
* if an empty or null collection was provided. Substitutes null items with a null-replacement value, if provided and is not null.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static String delimit(@NotNull final String[] values, @NotNull final String delimiter, String nullReplacementValue)
{
val sb = new StringBuilder(256);
for (String value : values)
if (value != null)
{
sb.append(value.toString());
sb.append(delimiter);
} else
// append null replacement
if (nullReplacementValue != null)
{
sb.append(nullReplacementValue);
sb.append(delimiter);
}
if (sb.length() > 0)
return sb.subSequence(0, sb.length() - delimiter.length()).toString();
return CONSTANT.EMPTY_STRING;
}
/**
* Concatenates the given chars with the given delimiter between all values. Returns String.Empty if an empty or null collection was
* provided.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static String delimit(@NotNull final char[] values, @NotNull final String delimiter)
{
val sb = new StringBuilder(256);
for (char value : values)
{
sb.append(value);
sb.append(delimiter);
}
if (sb.length() > 0)
return sb.subSequence(0, sb.length() - delimiter.length()).toString();
return CONSTANT.EMPTY_STRING;
}
/**
* Returns true if the value ends with a suffix.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static boolean endsWith(@NotNull final String value, char suffix)
{
if (value.length() == 0)
return false;
return value.charAt(value.length() - 1) == suffix;
}
/**
* Returns true if a value ends with a suffix. Uses the CurrentLocale string comparison.
*
* @throws NullPointerException An argument is null.
*/
public static boolean endsWith(String value, String suffix)
{
return endsWith(value, suffix, StringComparison.CurrentLocale);
}
/**
* Returns true if a value ends with a suffix. Uses the specified string comparison.
*
* @throws NullPointerException An argument is null.
*/
public static boolean endsWith(String value, String suffix, StringComparison stringComparison)
{
return lastIndexOf(value, suffix, value.length() - 1, 1, stringComparison) >= 0;
}
/**
* Returns true if a value ends with a suffix. Uses a culture-aware higher performance string comparison.
*
* @throws NullPointerException An argument is null.
*/
public static boolean endsWith(String value, String suffix, Locale locale, Collator collator, boolean caseSensitive)
{
return lastIndexOf(value, suffix, value.length() - 1, 1, locale, collator, caseSensitive) >= 0;
}
/**
* Returns true if a value equals with another. Uses the CurrentLocale string comparison.
*
* @throws NullPointerException An argument is null.
*/
public static boolean equal(String a, String b)
{
return equal(a, b, StringComparison.CurrentLocale);
}
/**
* Returns true if a value equals with another. Uses the specified string comparison.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static boolean equal(@NotNull final String a, @NotNull final String b, StringComparison stringComparison)
{
switch(stringComparison)
{
case CurrentLocale:
return equalLocaleSensitive(a, b, CURRENT_LOCALE, CURRENT_LOCALE_COLLATOR, true);
case CurrentLocaleIgnoreCase:
return equalLocaleSensitive(a, b, CURRENT_LOCALE, CURRENT_LOCALE_COLLATOR, false);
case InvariantLocale:
return equalLocaleSensitive(a, b, INVARIANT_LOCALE, INVARIANT_LOCALE_COLLATOR, true);
case InvariantLocaleIgnoreCase:
return equalLocaleSensitive(a, b, INVARIANT_LOCALE, INVARIANT_LOCALE_COLLATOR, false);
case Ordinal:
return equalOrdinal(a, b, true);
case OrdinalIgnoreCase:
return equalOrdinal(a, b, false);
default:
throw new IllegalArgumentException("stringComparison has an unexpected value: " + stringComparison.toString());
}
}
/**
* Returns true if a value equals with another. Uses a culture-aware higher performance string comparison.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static boolean equal(@NotNull final String a, @NotNull final String b, Locale locale, Collator collator, boolean caseSensitive)
{
return equalLocaleSensitive(a, b, locale, collator, caseSensitive);
}
/**
* Locale-aware string equality comparison.
*/
@Validate
private static boolean equalLocaleSensitive(String a, String b, @NotNull final Locale locale, @NotNull final Collator collator,
boolean caseSensitive)
{
if (!caseSensitive)
{
a = a.toLowerCase(locale);
b = b.toLowerCase(locale);
}
return collator.equals(a, b);
}
/**
* Compares two strings for equality
*/
private static boolean equalOrdinal(String a, String b, boolean caseSensitive)
{
if (a.length() != b.length())
return false;
return indexOfOrdinal(a, b, 0, 1, caseSensitive) == 0;
}
/**
* Finds the first index encountered of a particular character. Returns -1 if not found.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static int indexOf(@NotNull final char[] array, char ch)
{
for (int i = 0; i < array.length; i++)
if (array[i] == ch)
return i;
return -1;
}
/**
* Returns the first index where a part is encountered within a string value. If the part is not existent, -1 is returned. Uses the
* CurrentLocale string comparison.
*
* @throws NullPointerException An argument is null.
*/
public static int indexOf(String value, String part)
{
return indexOf(value, part, 0, value.length(), StringComparison.CurrentLocale);
}
/**
* Returns the first index where a part is encountered within a string value. If the part is not existent, -1 is returned. Uses the
* specified string comparison.
*
* @throws NullPointerException An argument is null.
*/
public static int indexOf(String value, String part, StringComparison stringComparison)
{
return indexOf(value, part, 0, value.length(), stringComparison);
}
/**
* Returns the first index where a part is encountered within a string value. If the part is not existent, -1 is returned. Uses a
* culture-aware higher performance string comparison.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static int
indexOf(@NotNull final String value, @NotNull final String part, Locale locale, Collator collator, boolean caseSensitive)
{
return indexOfLocaleSensitive(value, part, 0, value.length(), locale, collator, caseSensitive);
}
/**
* Returns the first, second, third, etc. index where a part is encountered within a string value, starting at the specified index and
* moving to the right of the string. If the part is not existent, -1 is returned. Uses the specified string comparison.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static int indexOf(@NotNull final String value, @NotNull final String part, int startIndex, int count,
StringComparison stringComparison)
{
switch(stringComparison)
{
case CurrentLocale:
return indexOfLocaleSensitive(value, part, startIndex, count, CURRENT_LOCALE, CURRENT_LOCALE_COLLATOR, true);
case CurrentLocaleIgnoreCase:
return indexOfLocaleSensitive(value, part, startIndex, count, CURRENT_LOCALE, CURRENT_LOCALE_COLLATOR, false);
case InvariantLocale:
return indexOfLocaleSensitive(value, part, startIndex, count, INVARIANT_LOCALE, INVARIANT_LOCALE_COLLATOR, true);
case InvariantLocaleIgnoreCase:
return indexOfLocaleSensitive(value, part, startIndex, count, INVARIANT_LOCALE, INVARIANT_LOCALE_COLLATOR, false);
case Ordinal:
return indexOfOrdinal(value, part, startIndex, count, true);
case OrdinalIgnoreCase:
return indexOfOrdinal(value, part, startIndex, count, false);
default:
throw new IllegalArgumentException("stringComparison has an unexpected value: " + stringComparison.toString());
}
}
/**
* Returns the first, second, third, etc. index where a part is encountered within a string value, starting at the specified index and
* moving to the right of the string. If the part is not existent, -1 is returned. Uses a culture-aware higher performance string
* comparison.
*
* @throws NullPointerException An argument is null.
* @throws IndexOutOfBoundsException An index is out of bounds
* @throws IllegalArgumentException An argument is out of range
*/
@Validate
public static int indexOf(@NotNull final String value, @NotNull final String part, int startIndex, int count, Locale locale,
Collator collator, boolean caseSensitive)
{
return indexOfLocaleSensitive(value, part, startIndex, count, locale, collator, caseSensitive);
}
/**
* Performs a locale-sensitive string comparison
*
* @param value The source value
* @param part The value we're looking for
* @param startIndex The index in source where we start looking
* @param count Up to how many positions to look forward
* @param locale The locale to use for toLowercase conversions, if a case sensitive comparison
* @param collator The collator to use to compare locale-sensitive strings
* @param caseSensitive Whether case sensitive or not
*
* @return The index where the part was found in value, or -1 if not found.
*
* @throws NullPointerException An argument is null.
* @throws IndexOutOfBoundsException An index is out of bounds
* @throws IllegalArgumentException An argument is out of range
*/
@Validate
private static int indexOfLocaleSensitive(String value, String part, int startIndex, int count, @NotNull final Locale locale,
@NotNull final Collator collator, boolean caseSensitive)
{
int valueLen = value.length();
int partLen = part.length();
int endIndex = startIndex + count;
if (startIndex > valueLen)
throw new IndexOutOfBoundsException("startIndex=" + startIndex + " valueLen=" + valueLen);
if (valueLen == 0)
if (partLen == 0)
return 0;
else
return -1;
if (startIndex < 0)
throw new IndexOutOfBoundsException("startIndex=" + startIndex);
if (count < 0 || endIndex > valueLen)
throw new IllegalArgumentException("count=" + count + " endIndex=" + endIndex + " valueLen=" + valueLen);
// select comparison type
if (caseSensitive)
// case-sensitive comparison from start position to end position
for (int i = startIndex; i < endIndex; i++)
// some Strings have different lengths but are equal
// e.g. for US: "\u00C4" "LATIN CAPITAL LETTER A WITH DIAERESIS" (Ä) and "\u0041\u0308" "LATIN CAPITAL LETTER A" (A) -
// "COMBINING DIAERESIS" (̈)
// therefore we have to examine whether the part is equal to ANY portion of the length of the string
for (int j = 1; j < valueLen - i + 1; j++)
{
String val = value.substring(i, i + j);
if (collator.equals(val, part))
return i;
}
else
{
String lowerPart = part.toLowerCase(locale);
// case-insensitive comparison from start position to end position
for (int i = startIndex; i < endIndex; i++)
// some Strings have different lengths but are equal such as the diaeresis example above,
// additionally (for this case) in some instances the string lengths of the toLowercase conversion will differ
// e.g. for LT: "\u00cc" (Ì) becomes 3 characters (i̇̀)
for (int j = 1; j < valueLen - i + 1; j++)
{
String val = value.substring(i, i + j);
if (collator.equals(val.toLowerCase(locale), lowerPart))
return i;
}
}
return -1;
}
/**
* Performs an ordinal string comparison.
*
* @param value The source value
* @param part The value we're looking for
* @param startIndex The index in source where we start looking
* @param count Up to how many positions to look forward
* @param caseSensitive Whether case sensitive or not
*
* @return The index where the part was found in value, or -1 if not found.
*
* @throws NullPointerException An argument is null.
* @throws IndexOutOfBoundsException An index is out of bounds
* @throws IllegalArgumentException An argument is out of range
*/
private static int indexOfOrdinal(String value, String part, int startIndex, int count, boolean caseSensitive)
{
int valueLen = value.length();
int partLen = part.length();
if (startIndex > valueLen)
throw new IndexOutOfBoundsException("startIndex=" + startIndex);
if (valueLen == 0)
if (partLen == 0)
return 0;
else
return -1;
if (startIndex < 0)
throw new IndexOutOfBoundsException("startIndex=" + startIndex);
if ((count < 0) || startIndex + count > valueLen || startIndex + count < 0)
throw new IllegalArgumentException("count=" + count + " startIndex=" + startIndex + " partLen=" + partLen);
// calculate the least amount of time we have to iterate through string characters
int minCount = valueLen - partLen + 1;
if (count + startIndex < minCount)
minCount = count + startIndex;
char[] vArr = value.toCharArray();
char[] pArr = part.toCharArray();
if (caseSensitive)
for (int i = startIndex; i < minCount; i++)
{
boolean found = true;
for (int j = 0; j < partLen; j++)
{
char vCh = vArr[i + j];
char pCh = pArr[j];
// compare chars
if (vCh != pCh)
{
found = false;
break;
}
}
if (found)
return i;
}
else
// case insensitive
for (int i = startIndex; i < minCount; i++)
{
boolean found = true;
for (int j = 0; j < partLen; j++)
{
char vCh = vArr[i + j];
char pCh = pArr[j];
// ASCII letters are converted to lowercase
if ((vCh >= 65 && vCh <= 90) || (vCh >= 97 && vCh <= 122))
{
vCh = Character.toLowerCase(vCh);
pCh = Character.toLowerCase(pCh);
}
// compare chars
if (vCh != pCh)
{
found = false;
break;
}
}
if (found)
return i;
}
return -1;
}
/**
* Returns the index of the first/second/third/etc. occurrence of an element in a value, starting from the left and moving forward.
*
* @throws NullPointerException An argument is null.
* @throws IllegalArgumentException Occurrence is out of range.
*/
@Validate
public static int indexOf(@NotNull final String value, @NotNull final String part, int occurrence, StringComparison stringComparison)
{
if (value.length() <= 0 || part.length() <= 0)
return 0;
if (occurrence <= 0)
throw new IllegalArgumentException("occurrence" + occurrence);
int result = 0;
int index = 0;
while ((index = indexOf(value, part, index, value.length() - index, stringComparison)) >= 0)
{
result++;
// check if occurrence reached, if so we found our result
if (result == occurrence)
return index;
index++;
}
return -1;
}
/**
* Returns the index of the first/second/third/etc. occurrence of an element in a value, starting from the left and moving forward. Uses a
* culture-aware higher performance string comparison.
*
* @throws NullPointerException An argument is null.
* @throws IllegalArgumentException Occurrence is out of range.
*/
@Validate
public static int indexOf(@NotNull final String value, @NotNull final String part, int occurrence, Locale locale, Collator collator,
boolean caseSensitive)
{
if (value.length() <= 0 || part.length() <= 0)
return 0;
if (occurrence <= 0)
throw new IllegalArgumentException("occurrence=" + occurrence);
int result = 0;
int index = 0;
while ((index = indexOf(value, part, index, value.length() - index, locale, collator, caseSensitive)) >= 0)
{
result++;
// check if occurrence reached, if so we found our result
if (result == occurrence)
return index;
index++;
}
return -1;
}
/**
* Inserts a string in a position in the given string.
*
* @throws NullPointerException An argument is null.
* @throws IndexOutOfBoundsException Index is out of range.
*/
@Validate
public static String insert(@NotNull final String value, int index, @NotNull final String insertedValue)
{
if (index < 0 || index > value.length())
throw new IndexOutOfBoundsException("index=" + index + " length=" + value.length());
return value.substring(0, index) + insertedValue + value.substring(index);
}
/**
* Returns true if the given string is null or empty.
*/
public static boolean isNullOrEmpty(String value)
{
return value == null || value.length() == 0;
}
/**
* Returns true if the given string is null or contains only whitespace chars (' ', '\t', '\r' and '\n').
*
* @author Marcin Lamparski
*/
public static boolean isNullOrBlank(String value)
{
return value == null || trim(value).length() == 0;
}
/**
* Finds the last index encountered of a particular character. Returns -1 if not found.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static int lastIndexOf(@NotNull final char[] array, char ch)
{
for (int i = array.length - 1; i >= 0; i--)
if (array[i] == ch)
return i;
return -1;
}
/**
* Returns the last index where a part is encountered within a string value. If the part is not existent, -1 is returned. Uses the
* CurrentLocale string comparison.
*
* @throws NullPointerException An argument is null.
*/
public static int lastIndexOf(String value, String part)
{
return lastIndexOf(value, part, StringComparison.CurrentLocale);
}
/**
* Returns the last index where a part is encountered within a string value. If the part is not existent, -1 is returned. Uses the
* specified string comparison.
*
* @throws NullPointerException An argument is null.
*/
public static int lastIndexOf(String value, String part, StringComparison stringComparison)
{
return lastIndexOf(value, part, value.length() - 1, value.length(), stringComparison);
}
/**
* Returns the last index where a part is encountered within a string value. If the part is not existent, -1 is returned. Uses a
* culture-aware higher performance string comparison.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static int lastIndexOf(@NotNull final String value, @NotNull final String part, Locale locale, Collator collator,
boolean caseSensitive)
{
return lastIndexOfLocaleSensitive(value, part, value.length() - 1, value.length(), locale, collator, caseSensitive);
}
/**
* Returns the first, second, third, etc. index where a part is encountered within a string value, starting at the specified index and
* moving to the left of the string. If the part is not existent, -1 is returned. Uses the specified string comparison.
*
* @throws NullPointerException An argument is null.
* @throws IndexOutOfBoundsException An index is out of bounds
* @throws IllegalArgumentException An argument is out of range
*/
@Validate
public static int lastIndexOf(@NotNull final String value, @NotNull final String part, int startIndex, int count,
StringComparison stringComparison)
{
switch(stringComparison)
{
case CurrentLocale:
return lastIndexOfLocaleSensitive(value, part, startIndex, count, CURRENT_LOCALE, CURRENT_LOCALE_COLLATOR, true);
case CurrentLocaleIgnoreCase:
return lastIndexOfLocaleSensitive(value, part, startIndex, count, CURRENT_LOCALE, CURRENT_LOCALE_COLLATOR, false);
case InvariantLocale:
return lastIndexOfLocaleSensitive(value, part, startIndex, count, INVARIANT_LOCALE, INVARIANT_LOCALE_COLLATOR, true);
case InvariantLocaleIgnoreCase:
return lastIndexOfLocaleSensitive(value, part, startIndex, count, INVARIANT_LOCALE, INVARIANT_LOCALE_COLLATOR, false);
case Ordinal:
return lastIndexOfOrdinal(value, part, startIndex, count, true);
case OrdinalIgnoreCase:
return lastIndexOfOrdinal(value, part, startIndex, count, false);
default:
throw new IllegalArgumentException("stringComparison has an unexpected value: " + stringComparison.toString());
}
}
/**
* Returns the first, second, third, etc. index where a part is encountered within a string value, starting at the specified index and
* moving to the left of the string. If the part is not existent, -1 is returned. Uses a culture-aware higher performance string
* comparison.
*
* @throws NullPointerException An argument is null.
* @throws IndexOutOfBoundsException An index is out of bounds
* @throws IllegalArgumentException An argument is out of range
*/
@Validate
public static int lastIndexOf(@NotNull final String value, @NotNull final String part, int startIndex, int count, Locale locale,
Collator collator, boolean caseSensitive)
{
return lastIndexOfLocaleSensitive(value, part, startIndex, count, locale, collator, caseSensitive);
}
/**
* Performs a locale-sensitive string comparison
*
* @param value The source value
* @param part The value we're looking for
* @param startIndex The index in source where we start looking
* @param count Up to how many positions to look backward
* @param locale The locale to use for toLowercase conversions, if a case sensitive comparison
* @param collator The collator to use to compare locale-sensitive strings
* @param caseSensitive Whether case sensitive or not
*
* @return The index where the part was found in value, or -1 if not found.
*
* @throws NullPointerException An argument is null.
* @throws IndexOutOfBoundsException An index is out of bounds
* @throws IllegalArgumentException An argument is out of range
*/
@Validate
private static int lastIndexOfLocaleSensitive(String value, String part, int startIndex, int count, @NotNull final Locale locale,
@NotNull final Collator collator, boolean caseSensitive)
{
int valueLen = value.length();
int partLen = part.length();
int endIndex = startIndex - count + 1;
if ((valueLen == 0) && ((startIndex == -1) || (startIndex == 0)))
if (partLen != 0)
return -1;
else
return 0;
if ((startIndex < 0) || (startIndex > valueLen))
throw new IndexOutOfBoundsException("startIndex=" + startIndex + " valueLen=" + valueLen);
if (count < 0 || endIndex < 0)
throw new IllegalArgumentException("count=" + count + " startIndex=" + startIndex);
// select comparison type
if (caseSensitive)
// case-sensitive comparison from start position to end position
for (int i = startIndex + 1; i > endIndex; i--)
// some Strings have different lengths but are equal
// e.g. for US: "\u00C4" "LATIN CAPITAL LETTER A WITH DIAERESIS" (Ä) and "\u0041\u0308" "LATIN CAPITAL LETTER A" (A) -
// "COMBINING DIAERESIS" (̈)
// therefore we have to examine whether the part is equal to ANY portion of the length of the string
for (int j = i - 1; j >= 0; j--)
{
String val = value.substring(j, i);
if (collator.equals(val, part))
return j;
}
else
{
String lowerPart = part.toLowerCase(locale);
// case-insensitive comparison from start position to end position
for (int i = startIndex + 1; i > endIndex; i--)
// some Strings have different lengths but are equal such as the diaeresis example above,
// additionally (for this case) in some instances the string lengths of the toLowercase conversion will differ
// e.g. for LT: "\u00cc" (Ì) becomes 3 characters (i̇̀)
for (int j = i - 1; j >= 0; j--)
{
String val = value.substring(j, i);
if (collator.equals(val.toLowerCase(locale), lowerPart))
return j;
}
}
return -1;
}
/**
* Performs an ordinal string comparison.
*
* @param value The source value
* @param part The value we're looking for
* @param startIndex The index in source where we start looking
* @param count Up to how many positions to look forward
* @param caseSensitive Whether case sensitive or not
*
* @return The index where the part was found in value, or -1 if not found.
*
* @throws NullPointerException An argument is null.
* @throws IndexOutOfBoundsException An index is out of bounds
* @throws IllegalArgumentException An argument is out of range
*/
private static int lastIndexOfOrdinal(String value, String part, int startIndex, int count, boolean caseSensitive)
{
int valueLen = value.length();
int partLen = part.length();
int endIndex = startIndex - count + 1;
if ((valueLen == 0) && (startIndex == -1 || startIndex == 0))
if (partLen != 0)
return -1;
else
return 0;
if ((startIndex < 0) || (startIndex > valueLen))
throw new IndexOutOfBoundsException("startIndex=" + startIndex + " valueLen=" + valueLen);
// following commented out: replaced by this
if ((count < 0) || endIndex < 0)
throw new IllegalArgumentException("count=" + count + " startIndex=" + startIndex);
// calculate the least amount of time we have to iterate through string characters
int minCount = startIndex - (valueLen - partLen);
if (endIndex > minCount)
minCount = endIndex;
char[] vArr = value.toCharArray();
char[] pArr = part.toCharArray();
if (caseSensitive)
for (int i = startIndex; i >= minCount; i--)
{
boolean found = true;
for (int j = 0; j < partLen; j++)
if (i - j < 0)
found = false;
else
{
char vCh = vArr[i - j];
char pCh = pArr[partLen - j - 1];
// compare chars
if (vCh != pCh)
{
found = false;
break;
}
}
if (found)
return i - partLen + 1;
}
else
// case insensitive
for (int i = startIndex; i >= minCount; i--)
{
boolean found = true;
for (int j = 0; j < partLen; j++)
if (i - j < 0)
found = false;
else
{
char vCh = vArr[i - j];
char pCh = pArr[partLen - j - 1];
// ASCII letters are converted to lowercase
if ((vCh >= 65 && vCh <= 90) || (vCh >= 97 && vCh <= 122))
{
vCh = Character.toLowerCase(vCh);
pCh = Character.toLowerCase(pCh);
}
// compare chars
if (vCh != pCh)
{
found = false;
break;
}
}
if (found)
return i - partLen + 1;
}
return -1;
}
/**
* Returns the index of the first/second/third/etc. occurrence of an element in a value, starting from the right and moving backward.
*
* @throws NullPointerException An argument is null.
* @throws IllegalArgumentException Occurrence is out of range.
*/
@Validate
public static int lastIndexOf(@NotNull final String value, @NotNull final String part, int occurrenceFromEnd,
StringComparison stringComparison)
{
if (value.length() <= 0 || part.length() <= 0)
return 0;
if (occurrenceFromEnd <= 0)
throw new IllegalArgumentException("occurrenceFromEnd" + occurrenceFromEnd);
int result = 0;
int index = value.length() - 1;
while ((index = lastIndexOf(value, part, index, index + 1, stringComparison)) >= 0)
{
result++;
// check if occurrence reached, if so we found our result
if (result == occurrenceFromEnd)
return index;
index--;
if (index < 0)
break;
}
return -1;
}
/**
* Returns the index of the first/second/third/etc. occurrence of an element in a value, starting from the right and moving backward. Uses
* a culture-aware higher performance string comparison.
*
* @throws NullPointerException An argument is null.
* @throws IllegalArgumentException Occurrence is out of range.
*/
@Validate
public static int lastIndexOf(@NotNull final String value, @NotNull final String part, int occurrenceFromEnd, Locale locale,
Collator collator, boolean caseSensitive)
{
if (value.length() <= 0 || part.length() <= 0)
return 0;
if (occurrenceFromEnd <= 0)
throw new IllegalArgumentException("occurrenceFromEnd" + occurrenceFromEnd);
int result = 0;
int index = value.length() - 1;
while ((index = lastIndexOf(value, part, index, index + 1, locale, collator, caseSensitive)) >= 0)
{
result++;
// check if occurrence reached, if so we found our result
if (result == occurrenceFromEnd)
return index;
index--;
if (index < 0)
break;
}
return -1;
}
/**
* Allows for matching a string to another, using Equals, StartsWith, EndsWith or Contains and a string comparison.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static boolean match(@NotNull final String a, MatchType stringMatch, @NotNull final String b, StringComparison stringComparison)
{
switch(stringMatch)
{
case Equals:
return equal(a, b, stringComparison);
case Contains:
return indexOf(a, b, stringComparison) >= 0;
case StartsWith:
return startsWith(a, b, stringComparison);
case EndsWith:
return endsWith(a, b, stringComparison);
default:
throw new IllegalArgumentException("Unrecognized string match type: " + stringMatch);
}
}
/**
* Allows for matching a string to another, using Equals, StartsWith, EndsWith or Contains and a string comparison. Uses a culture-aware
* higher performance string comparison.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static boolean match(@NotNull final String a, MatchType stringMatch, @NotNull final String b, Locale locale, Collator collator,
boolean caseSensitive)
{
switch(stringMatch)
{
case Equals:
return equal(a, b, locale, collator, caseSensitive);
case Contains:
return indexOf(a, b, locale, collator, caseSensitive) >= 0;
case StartsWith:
return startsWith(a, b, locale, collator, caseSensitive);
case EndsWith:
return endsWith(a, b, locale, collator, caseSensitive);
default:
throw new IllegalArgumentException("Unrecognized string match type: " + stringMatch);
}
}
/**
* Right-aligns the characters in this instance, padding on the left a specified character
*
* @throws NullPointerException An argument is null.
* @throws IllegalArgumentException An invalid argument was given.
*/
@Validate
public static String padRight(@NotNull final String value, int totalLength, char pad)
{
if (totalLength < 0)
throw new IllegalArgumentException("totalLength=" + totalLength);
int add = totalLength - value.length();
if (add < 0)
throw new IllegalArgumentException("totalLength=" + totalLength + " len=" + value.length());
StringBuilder str = new StringBuilder(value);
char[] ch = new char[add];
Arrays.fill(ch, pad);
str.append(ch);
return str.toString();
}
/**
* Left-aligns the characters in this instance, padding on the right a specified character
*
* @throws NullPointerException An argument is null.
* @throws IllegalArgumentException An invalid argument was given.
*/
@Validate
public static String padLeft(@NotNull final String value, int totalLength, char pad)
{
if (totalLength < 0)
throw new IllegalArgumentException("totalLength=" + totalLength);
int add = totalLength - value.length();
if (add < 0)
throw new IllegalArgumentException("totalLength=" + totalLength + " len=" + value.length());
StringBuilder str = new StringBuilder(value);
char[] ch = new char[add];
Arrays.fill(ch, pad);
str.insert(0, ch);
return str.toString();
}
/**
* Parses a boolean from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
public static boolean parseBool(String value)
{
return parseBool(value, CONSTANT.TRUE, CONSTANT.FALSE, StringComparison.OrdinalIgnoreCase);
}
/**
* Parses a boolean from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
@Validate
public static boolean parseBool(@NotNull final String value, @NotNull final String trueValue, @NotNull final String falseValue,
StringComparison comparisonType)
{
// parse
if (equal(trueValue, value, comparisonType))
return true;
else if (equal(falseValue, value, comparisonType))
return false;
// sanity check
throw new NumberFormatException("Value given was neither " + trueValue + " nor " + falseValue + ": " + value);
}
/**
* Parses the first character from a string.
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
public static char parseChar(String value)
{
return parseChar(value, Character.MIN_VALUE, Character.MAX_VALUE);
}
/**
* Parses the first character from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
@Validate
public static char parseChar(@NotNull final String value, char minValue, char maxValue)
{
if (value.length() != 1)
throw new NumberFormatException("Value is not 1 character long: " + value);
char result = value.charAt(0);
// sanity check
if (result < minValue)
throw new NumberFormatException("Value (" + result + ") was less than allowed minimum (" + minValue + ").");
if (result > maxValue)
throw new NumberFormatException("Value (" + result + ") was more than allowed maximum (" + maxValue + ").");
return result;
}
/**
* Parses a DateTime from a string. Uses common ISO formats as well as some locale-specific formats. See
* http://joda-time.sourceforge.net/apidocs/org/joda/time/format/DateTimeFormat.html ISO format examples:
* <ul>
* <li>yyyyMMdd'T'HHmmssZ</li>
* <li>yyyyMMdd'T'HHmmss.SSSZ</li>
* <li>yyyy-MM-dd</li>
* <li>yyyy-MM-dd'T'HH:mm:ss.SSS</li>
* <li>yyyy-MM-dd'T'HH:mm:ssZZ</li>
* <li>yyyy-MM-dd'T'HH:mm:ss.SSSZZ</li>
* <li>yyyy-MM-dd HH:mm:ss</li>
* <li>yyyy-MM-dd HH:mm:ss.SSSSSSS</li>
* <li>yyyy-MM-dd'T'HH:mm:ss</li>
* <li>yyyy-MM-dd'T'HH:mm:ss.SSSSSSS</li>
* </ul>
* <p/>
* Also supports non-ISO formats such as yyyy/MM/dd. Furthermore attempts to parse using locale-specific parsers.
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
@Validate
public static LocalDateTime parseDateTime(@NotNull final String value)
{
LocalDateTime result = null;
// attempt ISO standard parsing
try
{
result = STANDARD_FORMATTERS.parseDateTime(value).toLocalDateTime();
}
catch(Throwable e)
{
// continues parsing attempts
}
if (result == null)
// first try locale-specific date/time parsing
for (int dateStyle = DateFormat.FULL; dateStyle <= DateFormat.SHORT; dateStyle++)
for (int timeStyle = DateFormat.FULL; timeStyle <= DateFormat.SHORT; timeStyle++)
if (result == null)
try
{
// Parse with a default format
Date date = DateFormat.getDateTimeInstance(dateStyle, timeStyle, CURRENT_LOCALE).parse(value);
result = new LocalDateTime(date);
break;
}
catch(ParseException e)
{
continue;
}
if (result == null)
// now try locale-specific date parsing
for (int dateStyle = DateFormat.FULL; dateStyle <= DateFormat.SHORT; dateStyle++)
try
{
// Parse with a default format
Date date = DateFormat.getDateInstance(dateStyle, CURRENT_LOCALE).parse(value);
result = new LocalDateTime(date);
break;
}
catch(ParseException e)
{
continue;
}
if (result == null)
// lastly try locale-specific time parsing
for (int timeStyle = DateFormat.FULL; timeStyle <= DateFormat.SHORT; timeStyle++)
try
{
// Parse with a default format
Date date = DateFormat.getTimeInstance(timeStyle, CURRENT_LOCALE).parse(value);
result = new LocalDateTime(date);
break;
}
catch(ParseException e)
{
continue;
}
if (result == null)
throw new NumberFormatException("The specified date/time is not in an identifiable format: " + value);
// sanity check
if (result.compareTo(MIN_DATETIME) < 0)
throw new NumberFormatException("Value (" + result + ") was less than allowed minimum (" + MIN_DATETIME + ").");
if (result.compareTo(MAX_DATETIME) > 0)
throw new NumberFormatException("Value (" + result + ") was more than allowed maximum (" + MAX_DATETIME + ").");
return result;
}
/**
* Parses a DateTime from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
public static LocalDateTime parseDateTime(String value, DateTimeFormatter formatter)
{
return parseDateTime(value, MIN_DATETIME, MAX_DATETIME, formatter);
}
/**
* Parses a DateTime from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
@Validate
public static LocalDateTime parseDateTime(@NotNull final String value, @NotNull final LocalDateTime minValue,
@NotNull final LocalDateTime maxValue, @NotNull final DateTimeFormatter formatter)
{
// parse
LocalDateTime result = formatter.parseDateTime(value).toLocalDateTime();
// sanity check
if (result.compareTo(minValue) < 0)
throw new NumberFormatException("Value (" + result + ") was less than allowed minimum (" + minValue + ").");
if (result.compareTo(maxValue) > 0)
throw new NumberFormatException("Value (" + result + ") was more than allowed maximum (" + maxValue + ").");
return result;
}
/**
* Parses a decimal from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
@Validate
public static BigDecimal parseDecimal(@NotNull final String value)
{
// parse
BigDecimal result;
try
{
// check if the current locale uses the same decimal separator and grouping chars as expected by the parser
if (DECIMAL_SEPARATOR != CONSTANT.COMMA_CHAR)
{
// remove grouping separators and replace decimal separators to commas
String converted = StringUtils.replace(value, GROUPING_SEPARATOR + CONSTANT.EMPTY_STRING, CONSTANT.EMPTY_STRING,
StringComparison.Ordinal);
result = new BigDecimal(converted);
} else
result = new BigDecimal(value);
}
catch(Throwable e)
{
throw new NumberFormatException("The value '" + value + "' could not be parsed: " + e.getMessage());
}
return result;
}
/**
* Parses a decimal from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
@Validate
public static BigDecimal
parseDecimal(@NotNull final String value, @NotNull final BigDecimal minValue, @NotNull final BigDecimal maxValue)
{
// parse
BigDecimal result;
try
{
// check if the current locale uses the same decimal separator and grouping chars as expected by the parser
if (DECIMAL_SEPARATOR != CONSTANT.COMMA_CHAR)
{
// remove grouping separators and replace decimal separators to commas
String converted = StringUtils.replace(value, GROUPING_SEPARATOR + CONSTANT.EMPTY_STRING, CONSTANT.EMPTY_STRING,
StringComparison.Ordinal);
result = new BigDecimal(converted);
} else
result = new BigDecimal(value);
}
catch(Throwable e)
{
throw new NumberFormatException("The value '" + value + "' could not be parsed: " + e.getMessage());
}
// sanity check
if (result.compareTo(minValue) < 0)
throw new NumberFormatException("Value (" + result + ") was less than allowed minimum (" + minValue + ").");
if (result.compareTo(maxValue) > 0)
throw new NumberFormatException("Value (" + result + ") was more than allowed maximum (" + maxValue + ").");
return result;
}
/**
* Parses a double from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
public static double parseDouble(String value)
{
return parseDouble(value, -Double.MAX_VALUE, Double.MAX_VALUE, true, true);
}
/**
* Parses a double from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
@Validate
public static double parseDouble(@NotNull final String value, double minValue, double maxValue, boolean allowInfinity, boolean allowNaN)
{
// parse
double result;
try
{
// check if the current locale uses the same decimal separator and grouping chars as expected by the parser
if (DECIMAL_SEPARATOR != CONSTANT.COMMA_CHAR)
{
// remove grouping separators and replace decimal separators to commas
String converted = StringUtils.replace(value, GROUPING_SEPARATOR + CONSTANT.EMPTY_STRING, CONSTANT.EMPTY_STRING,
StringComparison.Ordinal);
result = Double.parseDouble(converted);
} else
result = Double.parseDouble(value);
}
catch(Throwable e)
{
throw new NumberFormatException("The value '" + value + "' could not be parsed: " + e.getMessage());
}
if (allowInfinity)
if (result == Double.POSITIVE_INFINITY || result == Double.NEGATIVE_INFINITY)
return result;
if (allowNaN)
if (result == Double.NaN)
return result;
// sanity check
if (result < minValue)
throw new NumberFormatException("Value (" + result + ") was less than allowed minimum (" + minValue + ").");
if (result > maxValue)
throw new NumberFormatException("Value (" + result + ") was more than allowed maximum (" + maxValue + ").");
return result;
}
/**
* Parses a float from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
public static float parseFloat(String value)
{
return parseFloat(value, -Float.MAX_VALUE, Float.MAX_VALUE, true, true);
}
/**
* Parses a float from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
@Validate
public static float parseFloat(@NotNull final String value, float minValue, float maxValue, boolean allowInfinity, boolean allowNaN)
{
// parse
float result;
try
{
// check if the current locale uses the same decimal separator and grouping chars as expected by the parser
if (DECIMAL_SEPARATOR != CONSTANT.COMMA_CHAR)
{
// remove grouping separators and replace decimal separators to commas
String converted = StringUtils.replace(value, GROUPING_SEPARATOR + CONSTANT.EMPTY_STRING, CONSTANT.EMPTY_STRING,
StringComparison.Ordinal);
result = Float.parseFloat(converted);
} else
result = Float.parseFloat(value);
}
catch(Throwable e)
{
throw new NumberFormatException("The value '" + value + "' could not be parsed: " + e.getMessage());
}
if (allowInfinity)
if (result == Double.POSITIVE_INFINITY || result == Double.NEGATIVE_INFINITY)
return result;
if (allowNaN)
if (result == Double.NaN)
return result;
// sanity check
if (result < minValue)
throw new NumberFormatException("Value (" + result + ") was less than allowed minimum (" + minValue + ").");
if (result > maxValue)
throw new NumberFormatException("Value (" + result + ") was more than allowed maximum (" + maxValue + ").");
return result;
}
/**
* Parses a byte from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
public static byte parseInt8(String value)
{
return parseInt8(value, Byte.MIN_VALUE, Byte.MAX_VALUE);
}
/**
* Parses a byte from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
@Validate
public static byte parseInt8(@NotNull final String value, byte minValue, byte maxValue)
{
// parse
byte result;
try
{
result = Byte.parseByte(value);
}
catch(Throwable e)
{
throw new NumberFormatException("The value '" + value + "' could not be parsed: " + e.getMessage());
}
// sanity check
if (result < minValue)
throw new NumberFormatException("Value (" + result + ") was less than allowed minimum (" + minValue + ").");
if (result > maxValue)
throw new NumberFormatException("Value (" + result + ") was more than allowed maximum (" + maxValue + ").");
return result;
}
/**
* Parses a short from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
public static short parseInt16(String value)
{
return parseInt16(value, Short.MIN_VALUE, Short.MAX_VALUE);
}
/**
* Parses a short from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
@Validate
public static short parseInt16(@NotNull final String value, short minValue, short maxValue)
{
// parse
short result;
try
{
result = Short.parseShort(value);
}
catch(Throwable e)
{
throw new NumberFormatException("The value '" + value + "' could not be parsed: " + e.getMessage());
}
// sanity check
if (result < minValue)
throw new NumberFormatException("Value (" + result + ") was less than allowed minimum (" + minValue + ").");
if (result > maxValue)
throw new NumberFormatException("Value (" + result + ") was more than allowed maximum (" + maxValue + ").");
return result;
}
/**
* Parses an int from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
public static int parseInt32(String value)
{
return parseInt32(value, Integer.MIN_VALUE, Integer.MAX_VALUE);
}
/**
* Parses an int from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
@Validate
public static int parseInt32(@NotNull final String value, int minValue, int maxValue)
{
// parse
int result;
try
{
result = Integer.parseInt(value);
}
catch(Throwable e)
{
throw new NumberFormatException("The value '" + value + "' could not be parsed: " + e.getMessage());
}
// sanity check
if (result < minValue)
throw new NumberFormatException("Value (" + result + ") was less than allowed minimum (" + minValue + ").");
if (result > maxValue)
throw new NumberFormatException("Value (" + result + ") was more than allowed maximum (" + maxValue + ").");
return result;
}
/**
* Parses a long from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
public static long parseInt64(String value)
{
return parseInt64(value, Long.MIN_VALUE, Long.MAX_VALUE);
}
/**
* Parses a long from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
@Validate
public static long parseInt64(@NotNull final String value, long minValue, long maxValue)
{
// parse
long result;
try
{
result = Long.parseLong(value);
}
catch(Throwable e)
{
throw new NumberFormatException("The value '" + value + "' could not be parsed: " + e.getMessage());
}
// sanity check
if (result < minValue)
throw new NumberFormatException("Value (" + result + ") was less than allowed minimum (" + minValue + ").");
if (result > maxValue)
throw new NumberFormatException("Value (" + result + ") was more than allowed maximum (" + maxValue + ").");
return result;
}
/**
* Parses an Int128 from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
public static Int128 parseInt128(String value)
{
return parseInt128(value, Int128.MIN_VALUE, Int128.MAX_VALUE);
}
/**
* Parses an Int128 from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
@Validate
public static Int128 parseInt128(@NotNull final String value, @NotNull final Int128 minValue, @NotNull final Int128 maxValue)
{
// parse
Int128 result;
try
{
result = new Int128(value);
}
catch(Throwable e)
{
throw new NumberFormatException("The value '" + value + "' could not be parsed: " + e.getMessage());
}
// sanity check
if (result.compareTo(minValue) < 0)
throw new NumberFormatException("Value (" + result + ") was less than allowed minimum (" + minValue + ").");
if (result.compareTo(maxValue) > 0)
throw new NumberFormatException("Value (" + result + ") was more than allowed maximum (" + maxValue + ").");
return result;
}
/**
* Parses the value of the given string: simply returns the string after checking for null.
*
* @throws NullPointerException When an argument is null
*/
@Validate
public static String parseString(@NotNull final String value)
{
return value;
}
/**
* Parses the value of the given object: simply returns the toString() result after checking for null, if the object is null the result is
* null.
*/
public static String parseString(Object value)
{
return value != null ? value.toString() : null;
}
/**
* Parses a TimeSpan from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
public static Duration parseTimeSpan(String value)
{
return parseTimeSpan(value, MIN_DURATION, MAX_DURATION);
}
/**
* Parses a TimeSpan from a string. TimeSpans are .NET structs and do not have an equivalent in Java. They express time durations in
* ticks, which are units 1000 times smaller than milliseconds.
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
@Validate
public static Duration parseTimeSpan(@NotNull final String value, @NotNull final Duration minValue, @NotNull final Duration maxValue)
{
Duration result;
try
{
result = new Duration(Long.parseLong(value) / 1000);
}
catch(Throwable e)
{
throw new NumberFormatException("The value '" + value + "' could not be parsed: " + e.getMessage());
}
// sanity check
if (result.compareTo(minValue) < 0)
throw new NumberFormatException("Value (" + result + ") was less than allowed minimum (" + minValue + ").");
if (result.compareTo(maxValue) > 0)
throw new NumberFormatException("Value (" + result + ") was more than allowed maximum (" + maxValue + ").");
return result;
}
/**
* Parses an sbyte from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
public static UnsignedByte parseUInt8(String value)
{
return parseUInt8(value, UnsignedByte.MIN_VALUE, UnsignedByte.MAX_VALUE);
}
/**
* Parses an sbyte from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
@Validate
public static UnsignedByte parseUInt8(@NotNull final String value, @NotNull final UnsignedByte minValue,
@NotNull final UnsignedByte maxValue)
{
// parse
UnsignedByte result;
try
{
result = new UnsignedByte(value);
}
catch(Throwable e)
{
throw new NumberFormatException("The value '" + value + "' could not be parsed: " + e.getMessage());
}
// sanity check
if (result.compareTo(minValue) < 0)
throw new NumberFormatException("Value (" + result + ") was less than allowed minimum (" + minValue + ").");
if (result.compareTo(maxValue) > 0)
throw new NumberFormatException("Value (" + result + ") was more than allowed maximum (" + maxValue + ").");
return result;
}
/**
* Parses a ushort from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
public static UnsignedShort parseUInt16(String value)
{
return parseUInt16(value, UnsignedShort.MIN_VALUE, UnsignedShort.MAX_VALUE);
}
/**
* Parses a ushort from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
@Validate
public static UnsignedShort parseUInt16(@NotNull final String value, @NotNull final UnsignedShort minValue,
@NotNull final UnsignedShort maxValue)
{
// parse
UnsignedShort result;
try
{
result = new UnsignedShort(value);
}
catch(Throwable e)
{
throw new NumberFormatException("The value '" + value + "' could not be parsed: " + e.getMessage());
}
// sanity check
if (result.compareTo(minValue) < 0)
throw new NumberFormatException("Value (" + result + ") was less than allowed minimum (" + minValue + ").");
if (result.compareTo(maxValue) > 0)
throw new NumberFormatException("Value (" + result + ") was more than allowed maximum (" + maxValue + ").");
return result;
}
/**
* Parses a uint from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
public static UnsignedInteger parseUInt32(String value)
{
return parseUInt32(value, UnsignedInteger.MIN_VALUE, UnsignedInteger.MIN_VALUE);
}
/**
* Parses a uint from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
@Validate
public static UnsignedInteger parseUInt32(@NotNull final String value, @NotNull final UnsignedInteger minValue,
@NotNull final UnsignedInteger maxValue)
{
// parse
UnsignedInteger result;
try
{
result = new UnsignedInteger(value);
}
catch(Throwable e)
{
throw new NumberFormatException("The value '" + value + "' could not be parsed: " + e.getMessage());
}
// sanity check
if (result.compareTo(minValue) < 0)
throw new NumberFormatException("Value (" + result + ") was less than allowed minimum (" + minValue + ").");
if (result.compareTo(maxValue) > 0)
throw new NumberFormatException("Value (" + result + ") was more than allowed maximum (" + maxValue + ").");
return result;
}
/**
* Parses a ulong from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
public static UnsignedLong parseUInt64(String value)
{
return parseUInt64(value, UnsignedLong.MIN_VALUE, UnsignedLong.MAX_VALUE);
}
/**
* Parses a ulong from a string
*
* @throws NullPointerException An argument is null.
* @throws NumberFormatException Parsed value is outside of configured range, or not of correct type.
*/
@Validate
public static UnsignedLong parseUInt64(@NotNull final String value, @NotNull final UnsignedLong minValue,
@NotNull final UnsignedLong maxValue)
{
// parse
UnsignedLong result;
try
{
result = new UnsignedLong(value);
}
catch(Throwable e)
{
throw new NumberFormatException("The value '" + value + "' could not be parsed: " + e.getMessage());
}
// sanity check
if (result.compareTo(minValue) < 0)
throw new NumberFormatException("Value (" + result + ") was less than allowed minimum (" + minValue + ").");
if (result.compareTo(maxValue) > 0)
throw new NumberFormatException("Value (" + result + ") was more than allowed maximum (" + maxValue + ").");
return result;
}
/**
* Replaces text in a value with the specified replacement text, using the given string comparison type.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static String replace(@NotNull String value, @NotNull final String textToReplace, @NotNull final String replaceWithText,
StringComparison stringComparison)
{
if (textToReplace.length() == 0)
return value;
int index = 0;
switch(stringComparison)
{
case CurrentLocale:
case CurrentLocaleIgnoreCase:
case InvariantLocale:
case InvariantLocaleIgnoreCase:
// for these we must not assume that the length is the same as textToReplace.length()
while ((index = indexOf(value, textToReplace, index, value.length() - index, stringComparison)) >= 0)
{
String prefix = value.substring(0, index);
for (int i = index + 1; i <= value.length(); i++)
{
// find index
String replace = value.substring(index, i);
if (equal(replace, textToReplace, stringComparison))
{
// end index found, replace
value = prefix + replaceWithText + value.substring(i);
break;
}
}
index += replaceWithText.length();
}
break;
case Ordinal:
case OrdinalIgnoreCase:
while ((index = indexOf(value, textToReplace, index, value.length() - index, stringComparison)) >= 0)
{
value = value.substring(0, index) + replaceWithText + value.substring(index + textToReplace.length());
index += replaceWithText.length();
}
break;
default:
throw new IllegalArgumentException("Unrecognized string comparison type: " + stringComparison);
}
return value;
}
/**
* Replaces text in a value with the specified replacement text, using the given string comparison type. Uses a culture-aware higher
* performance string comparison.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static String replace(@NotNull String value, @NotNull final String textToReplace, @NotNull final String replaceWithText,
Locale locale, Collator collator, boolean caseSensitive)
{
if (textToReplace.length() == 0)
return value;
int index = 0;
// for these we must not assume that the length is the same as textToReplace.length()
while ((index = indexOf(value, textToReplace, index, value.length() - index, locale, collator, caseSensitive)) >= 0)
{
String prefix = value.substring(0, index);
for (int i = index + 1; i <= value.length(); i++)
{
// find index
String replace = value.substring(index, i);
if (equal(replace, textToReplace, locale, collator, caseSensitive))
{
// end index found, replace
value = prefix + replaceWithText + value.substring(i);
break;
}
}
index += replaceWithText.length();
}
return value;
}
/**
* Replace method working on a string builder, for more efficient replacement.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static void replace(@NotNull final StringBuilder builder, @NotNull final String textToReplace,
@NotNull final String replaceWithText)
{
int indexOfTarget = -1;
while ((indexOfTarget = builder.indexOf(textToReplace)) > 0)
builder.replace(indexOfTarget, indexOfTarget + textToReplace.length(), replaceWithText);
}
/**
* Returns a number of ToString() result concatenations of the given character.
*
* @throws NullPointerException An argument is null.
* @throws IllegalArgumentException Repetitions argument is out of range.
*/
public static String repeat(char value, int repetitions)
{
return repeat(Character.toString(value), repetitions);
}
/**
* Returns a number of ToString() result concatenations of the given string value.
*
* @throws NullPointerException An argument is null.
* @throws IllegalArgumentException Repetitions argument is out of range.
*/
@Validate
public static String repeat(@NotNull final String value, int repetitions)
{
if (repetitions < 0)
throw new IllegalArgumentException("repetitions=" + repetitions);
StringBuilder sb = new StringBuilder(value.length() * repetitions);
for (int i = 0; i < repetitions; i++)
sb.append(value);
return sb.toString();
}
/**
* Reverses a string.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static String reverse(@NotNull final String value)
{
val sb = new StringBuilder(value);
return sb.reverse().toString();
}
/**
* Returns true if two character sequences are equal
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static boolean sequenceEqual(@NotNull final char[] a, @NotNull final char[] b)
{
if (a.length != b.length)
return false;
if (a.length == 0)
return false;
return sequenceEqual(a, 0, b, 0, a.length);
}
/**
* Returns true if two character sequences are equal
*
* @throws NullPointerException An argument is null.
* @throws IndexOutOfBoundsException An index is out of bounds.
* @throws IllegalArgumentException An argument is out of range.
*/
@Validate
public static boolean sequenceEqual(@NotNull final char[] a, int startIndexA, @NotNull final char[] b, int startIndexB, int count)
{
if (count == 0)
return true;
if (startIndexA < 0 || startIndexA > a.length)
throw new IndexOutOfBoundsException("startIndexA=" + startIndexA + " aLen=" + a.length);
if (startIndexB < 0 || startIndexB > b.length)
throw new IndexOutOfBoundsException("startIndexB=" + startIndexB + " bLen=" + b.length);
if (count < 0)
throw new IllegalArgumentException("count=" + count);
if (startIndexA + count > a.length || startIndexA + count < 0)
throw new IllegalArgumentException("startIndexA=" + startIndexA + " count=" + count + " aLen=" + a.length);
if (startIndexB + count > b.length || startIndexB + count < 0)
throw new IllegalArgumentException("startIndexB=" + startIndexB + " count=" + count + " bLen=" + b.length);
for (int i = 0; i < count; i++)
if (a[startIndexA + i] != b[startIndexB + i])
return false;
return true;
}
/**
* Splits a sequence into parts delimited by the specified delimited. Empty entries between delimiters are removed.
*
* @throws NullPointerException When an argument is null, or an item in the iterable is null.
*/
@Validate
public static List<char[]> split(@NotNull final char[] values, char delimiter)
{
List<ReifiedList<Character>> parts = new ArrayList<ReifiedList<Character>>();
parts.add(new ReifiedArrayList<Character>(Character.class));
for (char item : values)
if (item != delimiter)
parts.get(parts.size() - 1).add(item);
else
parts.add(new ReifiedArrayList<Character>(Character.class));
List<char[]> result = new ArrayList<char[]>();
for (ReifiedList<Character> arr : parts)
if (arr.size() > 0)
result.add(ArrayUtils.unbox(arr.toArray()));
return result;
}
/**
* Splits a string, using StringSplitOptions.RemoveEmptyEntries.
*
* @throws NullPointerException An argument is null.
*/
public static String[] split(String text, char delimiter)
{
return split(text, delimiter, StringSplitOptions.RemoveEmptyEntries);
}
/**
* Splits a string using the specified split option.
*
* @throws NullPointerException An argument is null.
*/
public static String[] split(String text, char delimiter, StringSplitOptions options)
{
char[] delimiters = new char[] {delimiter};
return split(text, delimiters, options);
}
/**
* Returns a string array that contains the substrings of the text instance that are delimited by elements of a specified Unicode
* character array.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static String[] split(@NotNull final String text, @NotNull final char[] delimiters, StringSplitOptions options)
{
val result = new ReifiedArrayList<String>(String.class);
// if no separators, return the original string
if (delimiters.length == 0)
{
result.add(text);
return result.toArray();
}
int lastFound = 0;
int index = 0;
for (char ch : text.toCharArray())
{
// check if character is a separator
if (contains(delimiters, ch))
{
if (lastFound == index)
result.add(CONSTANT.EMPTY_STRING);
else
// add part without separator
result.add(text.substring(lastFound, index));
// mark last found position
lastFound = index + 1;
}
index++;
}
// add last part if any
if (index > lastFound)
result.add(text.substring(lastFound, index));
else if (index == lastFound && text.length() > 0 && contains(delimiters, text.charAt(text.length() - 1)))
result.add(CONSTANT.EMPTY_STRING);
switch(options)
{
case None:
return result.toArray();
case RemoveEmptyEntries:
return Linq.where(result.toArray(), isNotNullOrEmpty());
default:
throw new IllegalArgumentException("stringSplitOptions has an unexpected value: " + options.toString());
}
}
/**
* Splits a string, using StringSplitOptions.RemoveEmptyEntries. When splitting strings, Ordinal string comparison is always used.
*
* @throws NullPointerException An argument is null.
*/
public static String[] split(String text, String delimiter)
{
return split(text, delimiter, StringSplitOptions.RemoveEmptyEntries);
}
/**
* Splits a string using the specified split option. When splitting strings, Ordinal string comparison is always used.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static String[] split(@NotNull final String text, @NotNull final String delimiter, StringSplitOptions options)
{
val delimiters = new String[] {delimiter};
return split(text, delimiters, options);
}
/**
* Returns a string array that contains the substrings of the text instance that are delimited by elements provided in the specified
* Unicode string array. When splitting strings, Ordinal string comparison is always used.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static String[] split(@NotNull final String text, @NotNull String[] delimiters, StringSplitOptions options)
{
// ignore null and empty delimiters
delimiters = Linq.where(delimiters, isNotNullOrEmpty());
// case where there are no delimiters
ReifiedList<String> result = new ReifiedArrayList<String>(String.class);
if (delimiters.length <= 0)
{
result.add(text);
return result.toArray();
}
// simplify if all delimiters are chars, call character delimiter method
if (Linq.all(delimiters, lengthEquals(1)))
return split(text, ArrayUtils.unbox(Linq.select(delimiters, charAt(0))), options);
// multiple delimiters, handled separately
result.add(text);
for (int i = 0; i < delimiters.length; i++)
{
ReifiedList<String> currentResults = new ReifiedArrayList<String>(String.class);
for (String part : result)
{
String[] splitParts = part.split(delimiters[i]);
for (String splitPart : splitParts)
currentResults.add(splitPart);
}
result = currentResults;
}
switch(options)
{
case None:
return result.toArray();
case RemoveEmptyEntries:
return Linq.toArray(Linq.where(result, isNotNullOrEmpty()), String.class);
default:
throw new IllegalArgumentException("Unrecognized string split option: " + options);
}
}
/**
* Splits a string by finding consecutive 'tags' i.e. delimiters. E.g. for 0d1h2m3s, using "d,h,m,s" as delimiters would return { 0,1,2,3
* }. Delimiters that are not found will be ignored. E.g. for 0d1h2m3s, using "d,m,h,s" as delimiters would return { 0,1h2,3 } (i.e. h not
* found after m). Uses Ordinal string comparison. Does not continuously split in the same way split() does, uses anchor points instead.
* When splitting strings, Ordinal string comparison is always used.
*
* @throws NullPointerException An argument is null.
* @throws IllegalArgumentException A delimiter is null or empty.
*/
@Validate
public static String[] splitAnchor(@NotNull String text, @NotNull final Iterable<String> delimiters)
{
// parts are stored here
val result = new ReifiedArrayList<String>(String.class);
// process delimiters serially
for (String delim : delimiters)
{
if (isNullOrEmpty(delim))
throw new IllegalArgumentException("A delimiter cannot be null or empty!");
if (!isNullOrEmpty(text))
{
ReifiedList<String> parts = new ReifiedArrayList<String>(split(text, delim));
if (parts.size() >= 2)
{
// store if any found
result.add(parts.get(0));
text = text.substring(parts.get(0).length() + 1);
}
}
}
return result.toArray();
}
/**
* Splits a string by finding consecutive 'tags' i.e. delimiters. E.g. for 0d1h2m3s, using "d,h,m,s" as delimiters would return { 0,1,2,3
* }. Delimiters that are not found will be ignored. E.g. for 0d1h2m3s, using "d,m,h,s" as delimiters would return { 0,1h2,3 } (i.e. h not
* found after m). Uses Ordinal string comparison. Does not continuously split in the same way split() does, uses anchor points instead.
* When splitting strings, Ordinal string comparison is always used.
*
* @throws NullPointerException An argument is null.
* @throws IllegalArgumentException A delimiter is null or empty.
*/
@Validate
public static String[] splitAnchor(String text, @NotNull final String[] delimiters)
{
return splitAnchor(text, Arrays.asList(delimiters));
}
/**
* Returns true if the value starts with a prefix.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static boolean startsWith(@NotNull final String value, char prefix)
{
if (value.length() == 0)
return false;
return value.charAt(0) == prefix;
}
/**
* Returns true if a value starts with a prefix. Uses the CurrentLocale string comparison.
*
* @throws NullPointerException An argument is null.
*/
public static boolean startsWith(String value, String prefix)
{
return indexOf(value, prefix, 0, value.length(), StringComparison.CurrentLocale) == 0;
}
/**
* Returns true if a value starts with a prefix. Uses the specified string comparison.
*
* @throws NullPointerException An argument is null.
*/
public static boolean startsWith(String value, String prefix, StringComparison stringComparison)
{
return indexOf(value, prefix, 0, 1, stringComparison) == 0;
}
/**
* Returns true if a value starts with a prefix. Uses a culture-aware higher performance string comparison.
*
* @throws NullPointerException An argument is null.
*/
public static boolean startsWith(String value, String prefix, Locale locale, Collator collator, boolean caseSensitive)
{
return indexOf(value, prefix, 0, 1, locale, collator, caseSensitive) == 0;
}
/**
* Similar to String.Substring of .NET, uses a length instead of endIndex.
*
* @throws NullPointerException An argument is null.
* @throws IndexOutOfBoundsException The length is out of range.
*/
public static String substring(String value, int length)
{
return substring(value, 0, length);
}
/**
* Similar to String.Substring of .NET, uses a length instead of endIndex.
*
* @throws NullPointerException An argument is null.
* @throws IndexOutOfBoundsException The index or length is out of range.
*/
@Validate
public static String substring(@NotNull final String value, int startIndex, int length)
{
int valueLen = value.length();
if (startIndex < 0 || startIndex >= valueLen)
throw new IndexOutOfBoundsException("startIndex=" + startIndex + " valueLen=" + valueLen);
if (length < 0 || startIndex + length > valueLen || startIndex + length < 0)
throw new IndexOutOfBoundsException("length=" + length + " startIndex=" + startIndex + " valueLen=" + valueLen);
return new String(value.toCharArray(), startIndex, length);
}
/**
* Title-cases a string
*
* @throws NullPointerException An argument is null
*/
@Validate
public static String titleCase(@NotNull final String value)
{
val parts = split(value, CONSTANT.WHITESPACE_CHAR, StringSplitOptions.None);
for (int i = 0; i < parts.length; i++)
if (parts[i].length() > 0)
parts[i] = parts[i].substring(0, 1).toUpperCase() + parts[i].substring(1).toLowerCase();
return delimit(parts, CONSTANT.WHITESPACE);
}
/**
* Returns a character range from start to end (inclusive)
*
* @throws NullPointerException An argument is null
* @throws IllegalArgumentException When the end is before start
*/
public static Character[] to(Character start, Character end)
{
return ArrayUtils.box(charRange(start.charValue(), end.charValue() + 1));
}
/**
* Trims a value's beginning of all instances of the given char. Does so repeatedly until no more matches are found.
*
* @throws NullPointerException When an argument is null.
*/
@Validate
public static String trimStart(@NotNull final String value, char ch)
{
return trimStart(value, new char[] {ch});
}
/**
* Trims a value's beginning of all the given chars. Does so repeatedly until no more matches are found.
*
* @throws NullPointerException When an argument is null.
*/
@Validate
public static String trimStart(@NotNull final String value, @NotNull final char[] chars)
{
int startIndex = 0;
while (startIndex <= value.length() - 1 && contains(chars, value.charAt(startIndex)))
startIndex++;
return value.substring(startIndex);
}
/**
* Trims a value's tail of all the instance of the given char. Does so repeatedly until no more matches are found.
*
* @throws NullPointerException When an argument is null.
*/
@Validate
public static String trimEnd(@NotNull final String value, char ch)
{
return trimEnd(value, new char[] {ch});
}
/**
* Trims a value's tail of all the given chars. Does so repeatedly until no more matches are found.
*
* @throws NullPointerException When an argument is null.
*/
@Validate
public static String trimEnd(@NotNull final String value, @NotNull final char[] chars)
{
int endIndex = value.length() - 1;
while (endIndex > 0 && contains(chars, value.charAt(endIndex)))
endIndex--;
return value.substring(0, endIndex + 1);
}
/**
* Trims a value of all whitespace chars, i.e. ' ', '\t', '\r', '\n'. Does so repeatedly until no more matches are found.
*
* @throws NullPointerException When an argument is null.
*/
public static String trim(String value)
{
return trim(value, CONSTANT.WHITESPACE_CHARS);
}
/**
* Trims a value of all the given chars. Does so repeatedly until no more matches are found.
*
* @throws NullPointerException When an argument is null.
*/
public static String trim(String value, char[] chars)
{
return trimEnd(trimStart(value, chars), chars);
}
/**
* Trims a value using the trimmed string.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static String trimStart(@NotNull String value, @NotNull final String trimmed, StringComparison stringComparison)
{
switch(stringComparison)
{
case CurrentLocale:
case CurrentLocaleIgnoreCase:
case InvariantLocale:
case InvariantLocaleIgnoreCase:
// we must not assume that the length is the same as trimmed.length()
while (startsWith(value, trimmed, stringComparison))
// find end position
for (int i = 0; i <= value.length(); i++)
if (equal(trimmed, value.substring(0, i), stringComparison))
{
value = value.substring(i);
break;
}
case Ordinal:
case OrdinalIgnoreCase:
while (startsWith(value, trimmed, stringComparison))
value = value.substring(trimmed.length());
break;
}
return value;
}
/**
* Trims a value using the trimmed string.
*
* @throws NullPointerException An argument is null.
*/
@Validate
public static String trimEnd(@NotNull String value, @NotNull final String trimmed, StringComparison stringComparison)
{
switch(stringComparison)
{
case CurrentLocale:
case CurrentLocaleIgnoreCase:
case InvariantLocale:
case InvariantLocaleIgnoreCase:
// we must not assume that the length is the same as trimmed.length()
while (endsWith(value, trimmed, stringComparison))
// find end position
for (int i = value.length() - 1; i >= 0; i--)
if (equal(trimmed, value.substring(i, value.length())))
{
value = value.substring(0, i);
break;
}
case Ordinal:
case OrdinalIgnoreCase:
while (endsWith(value, trimmed, stringComparison))
value = value.substring(0, value.length() - trimmed.length());
break;
}
return value;
}
/**
* Trims a value using the trimmed string.
*
* @throws NullPointerException An argument is null.
*/
public static String trim(String value, String trimmed, StringComparison stringComparison)
{
return trimEnd(trimStart(value, trimmed, stringComparison), trimmed, stringComparison);
}
/**
* Cuts the tail of a string, at the specified index.
*
* @throws NullPointerException An argument is null.
* @throws IndexOutOfBoundsException The index is out of bounds.
*/
@Validate
public static String truncate(@NotNull final String value, int endIndex)
{
if (endIndex < 0 || endIndex > value.length())
throw new IndexOutOfBoundsException("endIndex=" + endIndex + " length=" + value.length());
return value.substring(0, endIndex);
}
/**
* Cuts the tail of a string, if it exceeds a specified index, otherwise does nothing.
*
* @throws NullPointerException An argument is null.
* @throws IndexOutOfBoundsException The index is negative.
*/
@Validate
public static String truncateIfLonger(@NotNull final String value, int endIndex)
{
if (endIndex < 0)
throw new IndexOutOfBoundsException("endIndex=" + endIndex);
if (endIndex > value.length())
return value;
return value.substring(0, endIndex);
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<Boolean> tryParseBool(String value)
{
try
{
return new TryResult<Boolean>(parseBool(value));
}
catch(Throwable e)
{
return new TryResult<Boolean>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<Boolean> tryParseBool(String value, String trueValue, String falseValue, StringComparison comparisonType)
{
try
{
return new TryResult<Boolean>(parseBool(value, trueValue, falseValue, comparisonType));
}
catch(Throwable e)
{
return new TryResult<Boolean>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<Character> tryParseChar(String value)
{
try
{
return new TryResult<Character>(parseChar(value));
}
catch(Throwable e)
{
return new TryResult<Character>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<Character> tryParseChar(String value, char minValue, char maxValue)
{
try
{
return new TryResult<Character>(parseChar(value, minValue, maxValue));
}
catch(Throwable e)
{
return new TryResult<Character>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<LocalDateTime> tryParseDateTime(String value)
{
try
{
return new TryResult<LocalDateTime>(parseDateTime(value));
}
catch(Throwable e)
{
return new TryResult<LocalDateTime>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<LocalDateTime> tryParseDateTime(String value, DateTimeFormatter fmt)
{
try
{
return new TryResult<LocalDateTime>(parseDateTime(value, fmt));
}
catch(Throwable e)
{
return new TryResult<LocalDateTime>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<LocalDateTime> tryParseDateTime(String value, LocalDateTime minValue, LocalDateTime maxValue,
DateTimeFormatter fmt)
{
try
{
return new TryResult<LocalDateTime>(parseDateTime(value, minValue, maxValue, fmt));
}
catch(Throwable e)
{
return new TryResult<LocalDateTime>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<BigDecimal> tryParseDecimal(String value)
{
try
{
return new TryResult<BigDecimal>(parseDecimal(value));
}
catch(Throwable e)
{
return new TryResult<BigDecimal>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<BigDecimal> tryParseDecimal(String value, BigDecimal minValue, BigDecimal maxValue)
{
try
{
return new TryResult<BigDecimal>(parseDecimal(value, minValue, maxValue));
}
catch(Throwable e)
{
return new TryResult<BigDecimal>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<Double> tryParseDouble(String value)
{
try
{
return new TryResult<Double>(parseDouble(value));
}
catch(Throwable e)
{
return new TryResult<Double>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<Double> tryParseDouble(String value, double minValue, double maxValue, boolean allowInfinity, boolean allowNaN)
{
try
{
return new TryResult<Double>(parseDouble(value, minValue, maxValue, allowInfinity, allowNaN));
}
catch(Throwable e)
{
return new TryResult<Double>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<Float> tryParseFloat(String value)
{
try
{
return new TryResult<Float>(parseFloat(value));
}
catch(Throwable e)
{
return new TryResult<Float>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<Float> tryParseFloat(String value, float minValue, float maxValue, boolean allowInfinity, boolean allowNaN)
{
try
{
return new TryResult<Float>(parseFloat(value, minValue, maxValue, allowInfinity, allowNaN));
}
catch(Throwable e)
{
return new TryResult<Float>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<Byte> tryParseInt8(String value)
{
try
{
return new TryResult<Byte>(parseInt8(value));
}
catch(Throwable e)
{
return new TryResult<Byte>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<Byte> tryParseInt8(String value, byte minValue, byte maxValue)
{
try
{
return new TryResult<Byte>(parseInt8(value, minValue, maxValue));
}
catch(Throwable e)
{
return new TryResult<Byte>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<Short> tryParseInt16(String value)
{
try
{
return new TryResult<Short>(parseInt16(value));
}
catch(Throwable e)
{
return new TryResult<Short>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<Short> tryParseInt16(String value, short minValue, short maxValue)
{
try
{
return new TryResult<Short>(parseInt16(value, minValue, maxValue));
}
catch(Throwable e)
{
return new TryResult<Short>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<Integer> tryParseInt32(String value)
{
try
{
return new TryResult<Integer>(parseInt32(value));
}
catch(Throwable e)
{
return new TryResult<Integer>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<Integer> tryParseInt32(String value, int minValue, int maxValue)
{
try
{
return new TryResult<Integer>(parseInt32(value, minValue, maxValue));
}
catch(Throwable e)
{
return new TryResult<Integer>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<Long> tryParseInt64(String value)
{
try
{
return new TryResult<Long>(parseInt64(value));
}
catch(Throwable e)
{
return new TryResult<Long>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<Long> tryParseInt64(String value, long minValue, long maxValue)
{
try
{
return new TryResult<Long>(parseInt64(value, minValue, maxValue));
}
catch(Throwable e)
{
return new TryResult<Long>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<Int128> tryParseInt128(String value)
{
try
{
return new TryResult<Int128>(parseInt128(value));
}
catch(Throwable e)
{
return new TryResult<Int128>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<Int128> tryParseInt128(String value, Int128 minValue, Int128 maxValue)
{
try
{
return new TryResult<Int128>(parseInt128(value, minValue, maxValue));
}
catch(Throwable e)
{
return new TryResult<Int128>();
}
}
/**
* Tries to parse the given value. Supports IPv4 and IPv6.
* <p/>
* Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<InetAddress> tryParseIpAddress(String value)
{
try
{
return new TryResult<InetAddress>(Inet4Address.getByName(value));
}
catch(Throwable e)
{
try
{
return new TryResult<InetAddress>(InetAddress.getByName(value));
}
catch(Throwable e2)
{
return new TryResult<InetAddress>();
}
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<Duration> tryParseTimeSpan(String value)
{
try
{
return new TryResult<Duration>(parseTimeSpan(value));
}
catch(Throwable e)
{
return new TryResult<Duration>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<Duration> tryParseTimeSpan(String value, Duration minValue, Duration maxValue)
{
try
{
return new TryResult<Duration>(parseTimeSpan(value, minValue, maxValue));
}
catch(Throwable e)
{
return new TryResult<Duration>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<UnsignedByte> tryParseUInt8(String value)
{
try
{
return new TryResult<UnsignedByte>(parseUInt8(value));
}
catch(Throwable e)
{
return new TryResult<UnsignedByte>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<UnsignedByte> tryParseUInt8(String value, UnsignedByte minValue, UnsignedByte maxValue)
{
try
{
return new TryResult<UnsignedByte>(parseUInt8(value, minValue, maxValue));
}
catch(Throwable e)
{
return new TryResult<UnsignedByte>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<UnsignedShort> tryParseUInt16(String value)
{
try
{
return new TryResult<UnsignedShort>(parseUInt16(value));
}
catch(Throwable e)
{
return new TryResult<UnsignedShort>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<UnsignedShort> tryParseUInt16(String value, UnsignedShort minValue, UnsignedShort maxValue)
{
try
{
return new TryResult<UnsignedShort>(parseUInt16(value, minValue, maxValue));
}
catch(Throwable e)
{
return new TryResult<UnsignedShort>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<UnsignedInteger> tryParseUInt32(String value)
{
try
{
return new TryResult<UnsignedInteger>(parseUInt32(value));
}
catch(Throwable e)
{
return new TryResult<UnsignedInteger>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<UnsignedInteger> tryParseUInt32(String value, UnsignedInteger minValue, UnsignedInteger maxValue)
{
try
{
return new TryResult<UnsignedInteger>(parseUInt32(value, minValue, maxValue));
}
catch(Throwable e)
{
return new TryResult<UnsignedInteger>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<UnsignedLong> tryParseUInt64(String value)
{
try
{
return new TryResult<UnsignedLong>(parseUInt64(value));
}
catch(Throwable e)
{
return new TryResult<UnsignedLong>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<UnsignedLong> tryParseUInt64(String value, UnsignedLong minValue, UnsignedLong maxValue)
{
try
{
return new TryResult<UnsignedLong>(parseUInt64(value, minValue, maxValue));
}
catch(Throwable e)
{
return new TryResult<UnsignedLong>();
}
}
/**
* Tries to parse the given value. Does not throw exceptions while parsing under any circumstances.
*/
public static TryResult<UUID> tryParseUuid(String value)
{
try
{
return new TryResult<UUID>(UUID.fromString(value));
}
catch(Throwable e)
{
return new TryResult<UUID>();
}
}
/**
* Returns a character range from start (inclusive) to end (exclusive)
*
* @throws NullPointerException An argument is null
* @throws IllegalArgumentException When the end is before start
*/
public static Character[] until(Character start, Character end)
{
return ArrayUtils.box(charRange(start.charValue(), end.charValue()));
}
/**
* Returns ISO standard and other frequently used date/time parsers
*/
private static DateTimeParser[] createCommonDateTimeParsers()
{
return new DateTimeParser[] {
ISODateTimeFormat.basicDateTimeNoMillis().getParser(), // yyyyMMdd'T'HHmmssZ
ISODateTimeFormat.basicDateTime().getParser(), // yyyyMMdd'T'HHmmss.SSSZ
ISODateTimeFormat.dateHourMinuteSecondFraction().getParser(), // yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSS (only 3 ms positions used though)
ISODateTimeFormat.dateTimeNoMillis().getParser(), // yyyy-MM-dd'T'HH:mm:ssZZ
ISODateTimeFormat.dateTime().getParser(), // yyyy-MM-dd'T'HH:mm:ss.SSSZZ (ISO 8601)
DateTimeFormat.forPattern("EEE, dd MMM yyyy HH:mm:ss Z").getParser(),// RFC 2822
DateTimeFormat.forPattern("yyyy/MM/dd").getParser(), DateTimeFormat.forPattern("yyyy/MM/dd HH:mm").getParser(),
DateTimeFormat.forPattern("yyyy/MM/dd HH:mm:ss").getParser(), DateTimeFormat.forPattern("yyyy/MM/dd HH:mm:ss.SSSSSSSSS").getParser(),
DateTimeFormat.forPattern("yyyy-MM-dd").getParser(), DateTimeFormat.forPattern("yyyy-MM-dd HH:mm").getParser(),
DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").getParser(), DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSSS").getParser(),
DateTimeFormat.forPattern("yyyy.MM.dd").getParser(), DateTimeFormat.forPattern("yyyy.MM.dd HH:mm").getParser(),
DateTimeFormat.forPattern("yyyy.MM.dd HH:mm:ss").getParser(), DateTimeFormat.forPattern("yyyy.MM.dd HH:mm:ss.SSSSSSSSS").getParser(),
DateTimeFormat.forPattern("HH:mm").getParser(), DateTimeFormat.forPattern("HH:mm:ss").getParser(),
DateTimeFormat.forPattern("HH:mm:ss.SSSSSSSSS").getParser()};
}
private StringUtils()
{
}
}