NOTE: Generally prefer the standard {@link Arrays#asList} method. - * This {@code arrayToList} method is just meant to deal with an incoming Object - * value that might be an {@code Object[]} or a primitive array at runtime. - *
A {@code null} source value will be converted to an empty List.
- * @param source the (potentially primitive) array
- * @return the converted List result
- * @see ObjectUtils#toObjectArray(Object)
- * @see Arrays#asList(Object[])
- */
- @SuppressWarnings("rawtypes")
- public static List arrayToList(Object source) {
- return Arrays.asList(ObjectUtils.toObjectArray(source));
- }
-
- /**
- * Merge the given array into the given Collection.
- * @param array the array to merge (may be {@code null})
- * @param collection the target Collection to merge the array into
- */
- @SuppressWarnings("unchecked")
- public static Uses {@code Properties.propertyNames()} to even catch
- * default properties linked into the original Properties instance.
- * @param props the Properties instance to merge (may be {@code null})
- * @param map the target Map to merge the properties into
- */
- @SuppressWarnings("unchecked")
- public static Enforces the given instance to be present, rather than returning
- * {@code true} for an equal element as well.
- * @param collection the Collection to check
- * @param element the element to look for
- * @return {@code true} if found, {@code false} else
- */
- public static boolean containsInstance(Collection> collection, Object element) {
- if (collection != null) {
- for (Object candidate : collection) {
- if (candidate == element) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Return {@code true} if any element in '{@code candidates}' is
- * contained in '{@code source}'; otherwise returns {@code false}.
- * @param source the source Collection
- * @param candidates the candidates to search for
- * @return whether any of the candidates has been found
- */
- public static boolean containsAny(Collection> source, Collection> candidates) {
- if (isEmpty(source) || isEmpty(candidates)) {
- return false;
- }
- for (Object candidate : candidates) {
- if (source.contains(candidate)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Return the first element in '{@code candidates}' that is contained in
- * '{@code source}'. If no element in '{@code candidates}' is present in
- * '{@code source}' returns {@code null}. Iteration order is
- * {@link Collection} implementation specific.
- * @param source the source Collection
- * @param candidates the candidates to search for
- * @return the first present object, or {@code null} if not found
- */
- @SuppressWarnings("unchecked")
- public static Mainly for internal use within the framework.
- *
- * Thanks to Alex Ruiz for contributing several enhancements to this class!
- *
- * @author Juergen Hoeller
- * @author Keith Donald
- * @author Rod Johnson
- * @author Rob Harrop
- * @author Chris Beams
- * @author Sam Brannen
- * @since 19.03.2004
- * @see CollectionUtils
- */
-public abstract class ObjectUtils {
-
- private static final int INITIAL_HASH = 7;
- private static final int MULTIPLIER = 31;
-
- private static final String EMPTY_STRING = "";
- private static final String NULL_STRING = "null";
- private static final String ARRAY_START = "{";
- private static final String ARRAY_END = "}";
- private static final String EMPTY_ARRAY = ARRAY_START + ARRAY_END;
- private static final String ARRAY_ELEMENT_SEPARATOR = ", ";
-
-
- /**
- * Return whether the given throwable is a checked exception:
- * that is, neither a RuntimeException nor an Error.
- * @param ex the throwable to check
- * @return whether the throwable is a checked exception
- * @see Exception
- * @see RuntimeException
- * @see Error
- */
- public static boolean isCheckedException(Throwable ex) {
- return !(ex instanceof RuntimeException || ex instanceof Error);
- }
-
- /**
- * Check whether the given exception is compatible with the specified
- * exception types, as declared in a throws clause.
- * @param ex the exception to check
- * @param declaredExceptions the exception types declared in the throws clause
- * @return whether the given exception is compatible
- */
- public static boolean isCompatibleWithThrowsClause(Throwable ex, Class>... declaredExceptions) {
- if (!isCheckedException(ex)) {
- return true;
- }
- if (declaredExceptions != null) {
- for (Class> declaredException : declaredExceptions) {
- if (declaredException.isInstance(ex)) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Determine whether the given object is an array:
- * either an Object array or a primitive array.
- * @param obj the object to check
- */
- public static boolean isArray(Object obj) {
- return (obj != null && obj.getClass().isArray());
- }
-
- /**
- * Determine whether the given array is empty:
- * i.e. {@code null} or of zero length.
- * @param array the array to check
- * @see #isEmpty(Object)
- */
- public static boolean isEmpty(Object[] array) {
- return (array == null || array.length == 0);
- }
-
- /**
- * Determine whether the given object is empty.
- * This method supports the following object types.
- * If the given object is non-null and not one of the aforementioned
- * supported types, this method returns {@code false}.
- * @param obj the object to check
- * @return {@code true} if the object is {@code null} or empty
- * @since 4.2
- * @see ObjectUtils#isEmpty(Object[])
- * @see StringUtils#hasLength(CharSequence)
- * @see StringUtils#isEmpty(Object)
- * @see CollectionUtils#isEmpty(Collection)
- * @see CollectionUtils#isEmpty(Map)
- */
- @SuppressWarnings("rawtypes")
- public static boolean isEmpty(Object obj) {
- if (obj == null) {
- return true;
- }
-
- if (obj instanceof CharSequence) {
- return ((CharSequence) obj).length() == 0;
- }
- if (obj.getClass().isArray()) {
- return Array.getLength(obj) == 0;
- }
- if (obj instanceof Collection) {
- return ((Collection) obj).isEmpty();
- }
- if (obj instanceof Map) {
- return ((Map) obj).isEmpty();
- }
-
- // else
- return false;
- }
-
- /**
- * Check whether the given array contains the given element.
- * @param array the array to check (may be {@code null},
- * in which case the return value will always be {@code false})
- * @param element the element to check for
- * @return whether the element has been found in the given array
- */
- public static boolean containsElement(Object[] array, Object element) {
- if (array == null) {
- return false;
- }
- for (Object arrayEle : array) {
- if (nullSafeEquals(arrayEle, element)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Check whether the given array of enum constants contains a constant with the given name,
- * ignoring case when determining a match.
- * @param enumValues the enum values to check, typically the product of a call to MyEnum.values()
- * @param constant the constant name to find (must not be null or empty string)
- * @return whether the constant has been found in the given array
- */
- public static boolean containsConstant(Enum>[] enumValues, String constant) {
- return containsConstant(enumValues, constant, false);
- }
-
- /**
- * Check whether the given array of enum constants contains a constant with the given name.
- * @param enumValues the enum values to check, typically the product of a call to MyEnum.values()
- * @param constant the constant name to find (must not be null or empty string)
- * @param caseSensitive whether case is significant in determining a match
- * @return whether the constant has been found in the given array
- */
- public static boolean containsConstant(Enum>[] enumValues, String constant, boolean caseSensitive) {
- for (Enum> candidate : enumValues) {
- if (caseSensitive ?
- candidate.toString().equals(constant) :
- candidate.toString().equalsIgnoreCase(constant)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Case insensitive alternative to {@link Enum#valueOf(Class, String)}.
- * @param A {@code null} source value will be converted to an
- * empty Object array.
- * @param source the (potentially primitive) array
- * @return the corresponding object array (never {@code null})
- * @throws IllegalArgumentException if the parameter is not an array
- */
- public static Object[] toObjectArray(Object source) {
- if (source instanceof Object[]) {
- return (Object[]) source;
- }
- if (source == null) {
- return new Object[0];
- }
- if (!source.getClass().isArray()) {
- throw new IllegalArgumentException("Source is not an array: " + source);
- }
- int length = Array.getLength(source);
- if (length == 0) {
- return new Object[0];
- }
- Class> wrapperType = Array.get(source, 0).getClass();
- Object[] newArray = (Object[]) Array.newInstance(wrapperType, length);
- for (int i = 0; i < length; i++) {
- newArray[i] = Array.get(source, i);
- }
- return newArray;
- }
-
-
- //---------------------------------------------------------------------
- // Convenience methods for content-based equality/hash-code handling
- //---------------------------------------------------------------------
-
- /**
- * Determine if the given objects are equal, returning {@code true} if
- * both are {@code null} or {@code false} if only one is {@code null}.
- * Compares arrays with {@code Arrays.equals}, performing an equality
- * check based on the array elements rather than the array reference.
- * @param o1 first Object to compare
- * @param o2 second Object to compare
- * @return whether the given objects are equal
- * @see Object#equals(Object)
- * @see Arrays#equals
- */
- public static boolean nullSafeEquals(Object o1, Object o2) {
- if (o1 == o2) {
- return true;
- }
- if (o1 == null || o2 == null) {
- return false;
- }
- if (o1.equals(o2)) {
- return true;
- }
- if (o1.getClass().isArray() && o2.getClass().isArray()) {
- return arrayEquals(o1, o2);
- }
- return false;
- }
-
- /**
- * Compare the given arrays with {@code Arrays.equals}, performing an equality
- * check based on the array elements rather than the array reference.
- * @param o1 first array to compare
- * @param o2 second array to compare
- * @return whether the given objects are equal
- * @see #nullSafeEquals(Object, Object)
- * @see Arrays#equals
- */
- private static boolean arrayEquals(Object o1, Object o2) {
- if (o1 instanceof Object[] && o2 instanceof Object[]) {
- return Arrays.equals((Object[]) o1, (Object[]) o2);
- }
- if (o1 instanceof boolean[] && o2 instanceof boolean[]) {
- return Arrays.equals((boolean[]) o1, (boolean[]) o2);
- }
- if (o1 instanceof byte[] && o2 instanceof byte[]) {
- return Arrays.equals((byte[]) o1, (byte[]) o2);
- }
- if (o1 instanceof char[] && o2 instanceof char[]) {
- return Arrays.equals((char[]) o1, (char[]) o2);
- }
- if (o1 instanceof double[] && o2 instanceof double[]) {
- return Arrays.equals((double[]) o1, (double[]) o2);
- }
- if (o1 instanceof float[] && o2 instanceof float[]) {
- return Arrays.equals((float[]) o1, (float[]) o2);
- }
- if (o1 instanceof int[] && o2 instanceof int[]) {
- return Arrays.equals((int[]) o1, (int[]) o2);
- }
- if (o1 instanceof long[] && o2 instanceof long[]) {
- return Arrays.equals((long[]) o1, (long[]) o2);
- }
- if (o1 instanceof short[] && o2 instanceof short[]) {
- return Arrays.equals((short[]) o1, (short[]) o2);
- }
- return false;
- }
-
- /**
- * Return as hash code for the given object; typically the value of
- * {@code Object#hashCode()}}. If the object is an array,
- * this method will delegate to any of the {@code nullSafeHashCode}
- * methods for arrays in this class. If the object is {@code null},
- * this method returns 0.
- * @see Object#hashCode()
- * @see #nullSafeHashCode(Object[])
- * @see #nullSafeHashCode(boolean[])
- * @see #nullSafeHashCode(byte[])
- * @see #nullSafeHashCode(char[])
- * @see #nullSafeHashCode(double[])
- * @see #nullSafeHashCode(float[])
- * @see #nullSafeHashCode(int[])
- * @see #nullSafeHashCode(long[])
- * @see #nullSafeHashCode(short[])
- */
- public static int nullSafeHashCode(Object obj) {
- if (obj == null) {
- return 0;
- }
- if (obj.getClass().isArray()) {
- if (obj instanceof Object[]) {
- return nullSafeHashCode((Object[]) obj);
- }
- if (obj instanceof boolean[]) {
- return nullSafeHashCode((boolean[]) obj);
- }
- if (obj instanceof byte[]) {
- return nullSafeHashCode((byte[]) obj);
- }
- if (obj instanceof char[]) {
- return nullSafeHashCode((char[]) obj);
- }
- if (obj instanceof double[]) {
- return nullSafeHashCode((double[]) obj);
- }
- if (obj instanceof float[]) {
- return nullSafeHashCode((float[]) obj);
- }
- if (obj instanceof int[]) {
- return nullSafeHashCode((int[]) obj);
- }
- if (obj instanceof long[]) {
- return nullSafeHashCode((long[]) obj);
- }
- if (obj instanceof short[]) {
- return nullSafeHashCode((short[]) obj);
- }
- }
- return obj.hashCode();
- }
-
- /**
- * Return a hash code based on the contents of the specified array.
- * If {@code array} is {@code null}, this method returns 0.
- */
- public static int nullSafeHashCode(Object[] array) {
- if (array == null) {
- return 0;
- }
- int hash = INITIAL_HASH;
- for (Object element : array) {
- hash = MULTIPLIER * hash + nullSafeHashCode(element);
- }
- return hash;
- }
-
- /**
- * Return a hash code based on the contents of the specified array.
- * If {@code array} is {@code null}, this method returns 0.
- */
- public static int nullSafeHashCode(boolean[] array) {
- if (array == null) {
- return 0;
- }
- int hash = INITIAL_HASH;
- for (boolean element : array) {
- hash = MULTIPLIER * hash + hashCode(element);
- }
- return hash;
- }
-
- /**
- * Return a hash code based on the contents of the specified array.
- * If {@code array} is {@code null}, this method returns 0.
- */
- public static int nullSafeHashCode(byte[] array) {
- if (array == null) {
- return 0;
- }
- int hash = INITIAL_HASH;
- for (byte element : array) {
- hash = MULTIPLIER * hash + element;
- }
- return hash;
- }
-
- /**
- * Return a hash code based on the contents of the specified array.
- * If {@code array} is {@code null}, this method returns 0.
- */
- public static int nullSafeHashCode(char[] array) {
- if (array == null) {
- return 0;
- }
- int hash = INITIAL_HASH;
- for (char element : array) {
- hash = MULTIPLIER * hash + element;
- }
- return hash;
- }
-
- /**
- * Return a hash code based on the contents of the specified array.
- * If {@code array} is {@code null}, this method returns 0.
- */
- public static int nullSafeHashCode(double[] array) {
- if (array == null) {
- return 0;
- }
- int hash = INITIAL_HASH;
- for (double element : array) {
- hash = MULTIPLIER * hash + hashCode(element);
- }
- return hash;
- }
-
- /**
- * Return a hash code based on the contents of the specified array.
- * If {@code array} is {@code null}, this method returns 0.
- */
- public static int nullSafeHashCode(float[] array) {
- if (array == null) {
- return 0;
- }
- int hash = INITIAL_HASH;
- for (float element : array) {
- hash = MULTIPLIER * hash + hashCode(element);
- }
- return hash;
- }
-
- /**
- * Return a hash code based on the contents of the specified array.
- * If {@code array} is {@code null}, this method returns 0.
- */
- public static int nullSafeHashCode(int[] array) {
- if (array == null) {
- return 0;
- }
- int hash = INITIAL_HASH;
- for (int element : array) {
- hash = MULTIPLIER * hash + element;
- }
- return hash;
- }
-
- /**
- * Return a hash code based on the contents of the specified array.
- * If {@code array} is {@code null}, this method returns 0.
- */
- public static int nullSafeHashCode(long[] array) {
- if (array == null) {
- return 0;
- }
- int hash = INITIAL_HASH;
- for (long element : array) {
- hash = MULTIPLIER * hash + hashCode(element);
- }
- return hash;
- }
-
- /**
- * Return a hash code based on the contents of the specified array.
- * If {@code array} is {@code null}, this method returns 0.
- */
- public static int nullSafeHashCode(short[] array) {
- if (array == null) {
- return 0;
- }
- int hash = INITIAL_HASH;
- for (short element : array) {
- hash = MULTIPLIER * hash + element;
- }
- return hash;
- }
-
- /**
- * Return the same value as {@link Boolean#hashCode()}}.
- * @see Boolean#hashCode()
- */
- public static int hashCode(boolean bool) {
- return (bool ? 1231 : 1237);
- }
-
- /**
- * Return the same value as {@link Double#hashCode()}}.
- * @see Double#hashCode()
- */
- public static int hashCode(double dbl) {
- return hashCode(Double.doubleToLongBits(dbl));
- }
-
- /**
- * Return the same value as {@link Float#hashCode()}}.
- * @see Float#hashCode()
- */
- public static int hashCode(float flt) {
- return Float.floatToIntBits(flt);
- }
-
- /**
- * Return the same value as {@link Long#hashCode()}}.
- * @see Long#hashCode()
- */
- public static int hashCode(long lng) {
- return (int) (lng ^ (lng >>> 32));
- }
-
-
- //---------------------------------------------------------------------
- // Convenience methods for toString output
- //---------------------------------------------------------------------
-
- /**
- * Return a String representation of an object's overall identity.
- * @param obj the object (may be {@code null})
- * @return the object's identity as String representation,
- * or an empty String if the object was {@code null}
- */
- public static String identityToString(Object obj) {
- if (obj == null) {
- return EMPTY_STRING;
- }
- return obj.getClass().getName() + "@" + getIdentityHexString(obj);
- }
-
- /**
- * Return a hex String form of an object's identity hash code.
- * @param obj the object
- * @return the object's identity code in hex notation
- */
- public static String getIdentityHexString(Object obj) {
- return Integer.toHexString(System.identityHashCode(obj));
- }
-
- /**
- * Return a content-based String representation if {@code obj} is
- * not {@code null}; otherwise returns an empty String.
- * Differs from {@link #nullSafeToString(Object)} in that it returns
- * an empty String rather than "null" for a {@code null} value.
- * @param obj the object to build a display String for
- * @return a display String representation of {@code obj}
- * @see #nullSafeToString(Object)
- */
- public static String getDisplayString(Object obj) {
- if (obj == null) {
- return EMPTY_STRING;
- }
- return nullSafeToString(obj);
- }
-
- /**
- * Determine the class name for the given object.
- * Returns {@code "null"} if {@code obj} is {@code null}.
- * @param obj the object to introspect (may be {@code null})
- * @return the corresponding class name
- */
- public static String nullSafeClassName(Object obj) {
- return (obj != null ? obj.getClass().getName() : NULL_STRING);
- }
-
- /**
- * Return a String representation of the specified Object.
- * Builds a String representation of the contents in case of an array.
- * Returns {@code "null"} if {@code obj} is {@code null}.
- * @param obj the object to build a String representation for
- * @return a String representation of {@code obj}
- */
- public static String nullSafeToString(Object obj) {
- if (obj == null) {
- return NULL_STRING;
- }
- if (obj instanceof String) {
- return (String) obj;
- }
- if (obj instanceof Object[]) {
- return nullSafeToString((Object[]) obj);
- }
- if (obj instanceof boolean[]) {
- return nullSafeToString((boolean[]) obj);
- }
- if (obj instanceof byte[]) {
- return nullSafeToString((byte[]) obj);
- }
- if (obj instanceof char[]) {
- return nullSafeToString((char[]) obj);
- }
- if (obj instanceof double[]) {
- return nullSafeToString((double[]) obj);
- }
- if (obj instanceof float[]) {
- return nullSafeToString((float[]) obj);
- }
- if (obj instanceof int[]) {
- return nullSafeToString((int[]) obj);
- }
- if (obj instanceof long[]) {
- return nullSafeToString((long[]) obj);
- }
- if (obj instanceof short[]) {
- return nullSafeToString((short[]) obj);
- }
- String str = obj.toString();
- return (str != null ? str : EMPTY_STRING);
- }
-
- /**
- * Return a String representation of the contents of the specified array.
- * The String representation consists of a list of the array's elements,
- * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated
- * by the characters {@code ", "} (a comma followed by a space). Returns
- * {@code "null"} if {@code array} is {@code null}.
- * @param array the array to build a String representation for
- * @return a String representation of {@code array}
- */
- public static String nullSafeToString(Object[] array) {
- if (array == null) {
- return NULL_STRING;
- }
- int length = array.length;
- if (length == 0) {
- return EMPTY_ARRAY;
- }
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < length; i++) {
- if (i == 0) {
- sb.append(ARRAY_START);
- }
- else {
- sb.append(ARRAY_ELEMENT_SEPARATOR);
- }
- sb.append(String.valueOf(array[i]));
- }
- sb.append(ARRAY_END);
- return sb.toString();
- }
-
- /**
- * Return a String representation of the contents of the specified array.
- * The String representation consists of a list of the array's elements,
- * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated
- * by the characters {@code ", "} (a comma followed by a space). Returns
- * {@code "null"} if {@code array} is {@code null}.
- * @param array the array to build a String representation for
- * @return a String representation of {@code array}
- */
- public static String nullSafeToString(boolean[] array) {
- if (array == null) {
- return NULL_STRING;
- }
- int length = array.length;
- if (length == 0) {
- return EMPTY_ARRAY;
- }
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < length; i++) {
- if (i == 0) {
- sb.append(ARRAY_START);
- }
- else {
- sb.append(ARRAY_ELEMENT_SEPARATOR);
- }
-
- sb.append(array[i]);
- }
- sb.append(ARRAY_END);
- return sb.toString();
- }
-
- /**
- * Return a String representation of the contents of the specified array.
- * The String representation consists of a list of the array's elements,
- * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated
- * by the characters {@code ", "} (a comma followed by a space). Returns
- * {@code "null"} if {@code array} is {@code null}.
- * @param array the array to build a String representation for
- * @return a String representation of {@code array}
- */
- public static String nullSafeToString(byte[] array) {
- if (array == null) {
- return NULL_STRING;
- }
- int length = array.length;
- if (length == 0) {
- return EMPTY_ARRAY;
- }
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < length; i++) {
- if (i == 0) {
- sb.append(ARRAY_START);
- }
- else {
- sb.append(ARRAY_ELEMENT_SEPARATOR);
- }
- sb.append(array[i]);
- }
- sb.append(ARRAY_END);
- return sb.toString();
- }
-
- /**
- * Return a String representation of the contents of the specified array.
- * The String representation consists of a list of the array's elements,
- * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated
- * by the characters {@code ", "} (a comma followed by a space). Returns
- * {@code "null"} if {@code array} is {@code null}.
- * @param array the array to build a String representation for
- * @return a String representation of {@code array}
- */
- public static String nullSafeToString(char[] array) {
- if (array == null) {
- return NULL_STRING;
- }
- int length = array.length;
- if (length == 0) {
- return EMPTY_ARRAY;
- }
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < length; i++) {
- if (i == 0) {
- sb.append(ARRAY_START);
- }
- else {
- sb.append(ARRAY_ELEMENT_SEPARATOR);
- }
- sb.append("'").append(array[i]).append("'");
- }
- sb.append(ARRAY_END);
- return sb.toString();
- }
-
- /**
- * Return a String representation of the contents of the specified array.
- * The String representation consists of a list of the array's elements,
- * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated
- * by the characters {@code ", "} (a comma followed by a space). Returns
- * {@code "null"} if {@code array} is {@code null}.
- * @param array the array to build a String representation for
- * @return a String representation of {@code array}
- */
- public static String nullSafeToString(double[] array) {
- if (array == null) {
- return NULL_STRING;
- }
- int length = array.length;
- if (length == 0) {
- return EMPTY_ARRAY;
- }
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < length; i++) {
- if (i == 0) {
- sb.append(ARRAY_START);
- }
- else {
- sb.append(ARRAY_ELEMENT_SEPARATOR);
- }
-
- sb.append(array[i]);
- }
- sb.append(ARRAY_END);
- return sb.toString();
- }
-
- /**
- * Return a String representation of the contents of the specified array.
- * The String representation consists of a list of the array's elements,
- * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated
- * by the characters {@code ", "} (a comma followed by a space). Returns
- * {@code "null"} if {@code array} is {@code null}.
- * @param array the array to build a String representation for
- * @return a String representation of {@code array}
- */
- public static String nullSafeToString(float[] array) {
- if (array == null) {
- return NULL_STRING;
- }
- int length = array.length;
- if (length == 0) {
- return EMPTY_ARRAY;
- }
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < length; i++) {
- if (i == 0) {
- sb.append(ARRAY_START);
- }
- else {
- sb.append(ARRAY_ELEMENT_SEPARATOR);
- }
-
- sb.append(array[i]);
- }
- sb.append(ARRAY_END);
- return sb.toString();
- }
-
- /**
- * Return a String representation of the contents of the specified array.
- * The String representation consists of a list of the array's elements,
- * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated
- * by the characters {@code ", "} (a comma followed by a space). Returns
- * {@code "null"} if {@code array} is {@code null}.
- * @param array the array to build a String representation for
- * @return a String representation of {@code array}
- */
- public static String nullSafeToString(int[] array) {
- if (array == null) {
- return NULL_STRING;
- }
- int length = array.length;
- if (length == 0) {
- return EMPTY_ARRAY;
- }
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < length; i++) {
- if (i == 0) {
- sb.append(ARRAY_START);
- }
- else {
- sb.append(ARRAY_ELEMENT_SEPARATOR);
- }
- sb.append(array[i]);
- }
- sb.append(ARRAY_END);
- return sb.toString();
- }
-
- /**
- * Return a String representation of the contents of the specified array.
- * The String representation consists of a list of the array's elements,
- * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated
- * by the characters {@code ", "} (a comma followed by a space). Returns
- * {@code "null"} if {@code array} is {@code null}.
- * @param array the array to build a String representation for
- * @return a String representation of {@code array}
- */
- public static String nullSafeToString(long[] array) {
- if (array == null) {
- return NULL_STRING;
- }
- int length = array.length;
- if (length == 0) {
- return EMPTY_ARRAY;
- }
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < length; i++) {
- if (i == 0) {
- sb.append(ARRAY_START);
- }
- else {
- sb.append(ARRAY_ELEMENT_SEPARATOR);
- }
- sb.append(array[i]);
- }
- sb.append(ARRAY_END);
- return sb.toString();
- }
-
- /**
- * Return a String representation of the contents of the specified array.
- * The String representation consists of a list of the array's elements,
- * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated
- * by the characters {@code ", "} (a comma followed by a space). Returns
- * {@code "null"} if {@code array} is {@code null}.
- * @param array the array to build a String representation for
- * @return a String representation of {@code array}
- */
- public static String nullSafeToString(short[] array) {
- if (array == null) {
- return NULL_STRING;
- }
- int length = array.length;
- if (length == 0) {
- return EMPTY_ARRAY;
- }
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < length; i++) {
- if (i == 0) {
- sb.append(ARRAY_START);
- }
- else {
- sb.append(ARRAY_ELEMENT_SEPARATOR);
- }
- sb.append(array[i]);
- }
- sb.append(ARRAY_END);
- return sb.toString();
- }
-
-}
diff --git a/src/main/java/com/alibaba/excel/util/StringUtils.java b/src/main/java/com/alibaba/excel/util/StringUtils.java
index b4a58986..8210a190 100644
--- a/src/main/java/com/alibaba/excel/util/StringUtils.java
+++ b/src/main/java/com/alibaba/excel/util/StringUtils.java
@@ -1,1317 +1,13 @@
package com.alibaba.excel.util;
-/*
- * Copyright 2002-2017 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Properties;
-import java.util.Set;
-import java.util.StringTokenizer;
-import java.util.TimeZone;
-import java.util.UUID;
-
-import org.apache.commons.codec.binary.CharSequenceUtils;
-
/**
- * Miscellaneous {@link String} utility methods.
- *
- * Mainly for internal use within the framework; consider
- * Apache's Commons Lang
- * for a more comprehensive suite of {@code String} utilities.
- *
- * This class delivers some simple functionality that should really be
- * provided by the core Java {@link String} and {@link StringBuilder}
- * classes. It also provides easy-to-use methods to convert between
- * delimited strings, such as CSV strings, and collections and arrays.
- *
- * @author Rod Johnson
- * @author Juergen Hoeller
- * @author Keith Donald
- * @author Rob Harrop
- * @author Rick Evans
- * @author Arjen Poutsma
- * @author Sam Brannen
- * @author Brian Clozel
- * @since 16 April 2001
+ * String utils
+ *
+ * @author jipengfei
*/
-public abstract class StringUtils {
-
- private static final String FOLDER_SEPARATOR = "/";
-
- private static final String WINDOWS_FOLDER_SEPARATOR = "\\";
-
- private static final String TOP_PATH = "..";
-
- private static final String CURRENT_PATH = ".";
-
- private static final char EXTENSION_SEPARATOR = '.';
-
-
- //---------------------------------------------------------------------
- // General convenience methods for working with Strings
- //---------------------------------------------------------------------
+public class StringUtils {
- /**
- * Check whether the given {@code String} is empty.
- * This method accepts any Object as an argument, comparing it to
- * {@code null} and the empty String. As a consequence, this method
- * will never return {@code true} for a non-null non-String object.
- * The Object signature is useful for general attribute handling code
- * that commonly deals with Strings but generally has to iterate over
- * Objects since attributes may e.g. be primitive value objects as well.
- * @param str the candidate String
- * @since 3.2.1
- */
public static boolean isEmpty(Object str) {
return (str == null || "".equals(str));
}
-
- /**
- * Check that the given {@code CharSequence} is neither {@code null} nor
- * of length 0.
- * Note: this method returns {@code true} for a {@code CharSequence}
- * that purely consists of whitespace.
- * Note: this method returns {@code true} for a {@code String} that
- * purely consists of whitespace.
- * @param str the {@code String} to check (may be {@code null})
- * @return {@code true} if the {@code String} is not {@code null} and has length
- * @see #hasLength(CharSequence)
- * @see #hasText(String)
- */
- public static boolean hasLength(String str) {
- return (str != null && !str.isEmpty());
- }
-
- /**
- * Check whether the given {@code CharSequence} contains actual text.
- * More specifically, this method returns {@code true} if the
- * {@code CharSequence} is not {@code null}, its length is greater than
- * 0, and it contains at least one non-whitespace character.
- * More specifically, this method returns {@code true} if the
- * {@code String} is not {@code null}, its length is greater than 0,
- * and it contains at least one non-whitespace character.
- * @param str the {@code String} to check (may be {@code null})
- * @return {@code true} if the {@code String} is not {@code null}, its
- * length is greater than 0, and it does not contain whitespace only
- * @see #hasText(CharSequence)
- */
- public static boolean hasText(String str) {
- return (hasLength(str) && containsText(str));
- }
-
- private static boolean containsText(CharSequence str) {
- int strLen = str.length();
- for (int i = 0; i < strLen; i++) {
- if (!Character.isWhitespace(str.charAt(i))) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Check whether the given {@code CharSequence} contains any whitespace characters.
- * @param str the {@code CharSequence} to check (may be {@code null})
- * @return {@code true} if the {@code CharSequence} is not empty and
- * contains at least 1 whitespace character
- * @see Character#isWhitespace
- */
- public static boolean containsWhitespace(CharSequence str) {
- if (!hasLength(str)) {
- return false;
- }
-
- int strLen = str.length();
- for (int i = 0; i < strLen; i++) {
- if (Character.isWhitespace(str.charAt(i))) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Check whether the given {@code String} contains any whitespace characters.
- * @param str the {@code String} to check (may be {@code null})
- * @return {@code true} if the {@code String} is not empty and
- * contains at least 1 whitespace character
- * @see #containsWhitespace(CharSequence)
- */
- public static boolean containsWhitespace(String str) {
- return containsWhitespace((CharSequence) str);
- }
-
- /**
- * Trim leading and trailing whitespace from the given {@code String}.
- * @param str the {@code String} to check
- * @return the trimmed {@code String}
- * @see Character#isWhitespace
- */
- public static String trimWhitespace(String str) {
- if (!hasLength(str)) {
- return str;
- }
-
- StringBuilder sb = new StringBuilder(str);
- while (sb.length() > 0 && Character.isWhitespace(sb.charAt(0))) {
- sb.deleteCharAt(0);
- }
- while (sb.length() > 0 && Character.isWhitespace(sb.charAt(sb.length() - 1))) {
- sb.deleteCharAt(sb.length() - 1);
- }
- return sb.toString();
- }
-
- /**
- * Trim all whitespace from the given {@code String}:
- * leading, trailing, and in between characters.
- * @param str the {@code String} to check
- * @return the trimmed {@code String}
- * @see Character#isWhitespace
- */
- public static String trimAllWhitespace(String str) {
- if (!hasLength(str)) {
- return str;
- }
-
- int len = str.length();
- StringBuilder sb = new StringBuilder(str.length());
- for (int i = 0; i < len; i++) {
- char c = str.charAt(i);
- if (!Character.isWhitespace(c)) {
- sb.append(c);
- }
- }
- return sb.toString();
- }
-
- /**
- * Trim leading whitespace from the given {@code String}.
- * @param str the {@code String} to check
- * @return the trimmed {@code String}
- * @see Character#isWhitespace
- */
- public static String trimLeadingWhitespace(String str) {
- if (!hasLength(str)) {
- return str;
- }
-
- StringBuilder sb = new StringBuilder(str);
- while (sb.length() > 0 && Character.isWhitespace(sb.charAt(0))) {
- sb.deleteCharAt(0);
- }
- return sb.toString();
- }
-
- /**
- * Trim trailing whitespace from the given {@code String}.
- * @param str the {@code String} to check
- * @return the trimmed {@code String}
- * @see Character#isWhitespace
- */
- public static String trimTrailingWhitespace(String str) {
- if (!hasLength(str)) {
- return str;
- }
-
- StringBuilder sb = new StringBuilder(str);
- while (sb.length() > 0 && Character.isWhitespace(sb.charAt(sb.length() - 1))) {
- sb.deleteCharAt(sb.length() - 1);
- }
- return sb.toString();
- }
-
- /**
- * Trim all occurrences of the supplied leading character from the given {@code String}.
- * @param str the {@code String} to check
- * @param leadingCharacter the leading character to be trimmed
- * @return the trimmed {@code String}
- */
- public static String trimLeadingCharacter(String str, char leadingCharacter) {
- if (!hasLength(str)) {
- return str;
- }
-
- StringBuilder sb = new StringBuilder(str);
- while (sb.length() > 0 && sb.charAt(0) == leadingCharacter) {
- sb.deleteCharAt(0);
- }
- return sb.toString();
- }
-
- /**
- * Trim all occurrences of the supplied trailing character from the given {@code String}.
- * @param str the {@code String} to check
- * @param trailingCharacter the trailing character to be trimmed
- * @return the trimmed {@code String}
- */
- public static String trimTrailingCharacter(String str, char trailingCharacter) {
- if (!hasLength(str)) {
- return str;
- }
-
- StringBuilder sb = new StringBuilder(str);
- while (sb.length() > 0 && sb.charAt(sb.length() - 1) == trailingCharacter) {
- sb.deleteCharAt(sb.length() - 1);
- }
- return sb.toString();
- }
-
- /**
- * Test if the given {@code String} starts with the specified prefix,
- * ignoring upper/lower case.
- * @param str the {@code String} to check
- * @param prefix the prefix to look for
- * @see String#startsWith
- */
- public static boolean startsWithIgnoreCase(String str, String prefix) {
- return (str != null && prefix != null && str.length() >= prefix.length() &&
- str.regionMatches(true, 0, prefix, 0, prefix.length()));
- }
-
- /**
- * Test if the given {@code String} ends with the specified suffix,
- * ignoring upper/lower case.
- * @param str the {@code String} to check
- * @param suffix the suffix to look for
- * @see String#endsWith
- */
- public static boolean endsWithIgnoreCase(String str, String suffix) {
- return (str != null && suffix != null && str.length() >= suffix.length() &&
- str.regionMatches(true, str.length() - suffix.length(), suffix, 0, suffix.length()));
- }
-
- /**
- * Test whether the given string matches the given substring
- * at the given index.
- * @param str the original string (or StringBuilder)
- * @param index the index in the original string to start matching against
- * @param substring the substring to match at the given index
- */
- public static boolean substringMatch(CharSequence str, int index, CharSequence substring) {
- if (index + substring.length() > str.length()) {
- return false;
- }
- for (int i = 0; i < substring.length(); i++) {
- if (str.charAt(index + i) != substring.charAt(i)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Count the occurrences of the substring {@code sub} in string {@code str}.
- * @param str string to search in
- * @param sub string to search for
- */
- public static int countOccurrencesOf(String str, String sub) {
- if (!hasLength(str) || !hasLength(sub)) {
- return 0;
- }
-
- int count = 0;
- int pos = 0;
- int idx;
- while ((idx = str.indexOf(sub, pos)) != -1) {
- ++count;
- pos = idx + sub.length();
- }
- return count;
- }
-
- /**
- * Replace all occurrences of a substring within a string with another string.
- * @param inString {@code String} to examine
- * @param oldPattern {@code String} to replace
- * @param newPattern {@code String} to insert
- * @return a {@code String} with the replacements
- */
- public static String replace(String inString, String oldPattern, String newPattern) {
- if (!hasLength(inString) || !hasLength(oldPattern) || newPattern == null) {
- return inString;
- }
- int index = inString.indexOf(oldPattern);
- if (index == -1) {
- // no occurrence -> can return input as-is
- return inString;
- }
-
- int capacity = inString.length();
- if (newPattern.length() > oldPattern.length()) {
- capacity += 16;
- }
- StringBuilder sb = new StringBuilder(capacity);
-
- int pos = 0; // our position in the old string
- int patLen = oldPattern.length();
- while (index >= 0) {
- sb.append(inString.substring(pos, index));
- sb.append(newPattern);
- pos = index + patLen;
- index = inString.indexOf(oldPattern, pos);
- }
-
- // append any characters to the right of a match
- sb.append(inString.substring(pos));
- return sb.toString();
- }
-
- /**
- * Delete all occurrences of the given substring.
- * @param inString the original {@code String}
- * @param pattern the pattern to delete all occurrences of
- * @return the resulting {@code String}
- */
- public static String delete(String inString, String pattern) {
- return replace(inString, pattern, "");
- }
-
- /**
- * Delete any character in a given {@code String}.
- * @param inString the original {@code String}
- * @param charsToDelete a set of characters to delete.
- * E.g. "az\n" will delete 'a's, 'z's and new lines.
- * @return the resulting {@code String}
- */
- public static String deleteAny(String inString, String charsToDelete) {
- if (!hasLength(inString) || !hasLength(charsToDelete)) {
- return inString;
- }
-
- StringBuilder sb = new StringBuilder(inString.length());
- for (int i = 0; i < inString.length(); i++) {
- char c = inString.charAt(i);
- if (charsToDelete.indexOf(c) == -1) {
- sb.append(c);
- }
- }
- return sb.toString();
- }
-
-
- //---------------------------------------------------------------------
- // Convenience methods for working with formatted Strings
- //---------------------------------------------------------------------
-
- /**
- * Quote the given {@code String} with single quotes.
- * @param str the input {@code String} (e.g. "myString")
- * @return the quoted {@code String} (e.g. "'myString'"),
- * or {@code null} if the input was {@code null}
- */
- public static String quote(String str) {
- return (str != null ? "'" + str + "'" : null);
- }
-
- /**
- * Turn the given Object into a {@code String} with single quotes
- * if it is a {@code String}; keeping the Object as-is else.
- * @param obj the input Object (e.g. "myString")
- * @return the quoted {@code String} (e.g. "'myString'"),
- * or the input object as-is if not a {@code String}
- */
- public static Object quoteIfString(Object obj) {
- return (obj instanceof String ? quote((String) obj) : obj);
- }
-
- /**
- * Unqualify a string qualified by a '.' dot character. For example,
- * "this.name.is.qualified", returns "qualified".
- * @param qualifiedName the qualified name
- */
- public static String unqualify(String qualifiedName) {
- return unqualify(qualifiedName, '.');
- }
-
- /**
- * Unqualify a string qualified by a separator character. For example,
- * "this:name:is:qualified" returns "qualified" if using a ':' separator.
- * @param qualifiedName the qualified name
- * @param separator the separator
- */
- public static String unqualify(String qualifiedName, char separator) {
- return qualifiedName.substring(qualifiedName.lastIndexOf(separator) + 1);
- }
-
- /**
- * Capitalize a {@code String}, changing the first letter to
- * upper case as per {@link Character#toUpperCase(char)}.
- * No other letters are changed.
- * @param str the {@code String} to capitalize
- * @return the capitalized {@code String}
- */
- public static String capitalize(String str) {
- return changeFirstCharacterCase(str, true);
- }
-
- /**
- * Uncapitalize a {@code String}, changing the first letter to
- * lower case as per {@link Character#toLowerCase(char)}.
- * No other letters are changed.
- * @param str the {@code String} to uncapitalize
- * @return the uncapitalized {@code String}
- */
- public static String uncapitalize(String str) {
- return changeFirstCharacterCase(str, false);
- }
-
- private static String changeFirstCharacterCase(String str, boolean capitalize) {
- if (!hasLength(str)) {
- return str;
- }
-
- char baseChar = str.charAt(0);
- char updatedChar;
- if (capitalize) {
- updatedChar = Character.toUpperCase(baseChar);
- }
- else {
- updatedChar = Character.toLowerCase(baseChar);
- }
- if (baseChar == updatedChar) {
- return str;
- }
-
- char[] chars = str.toCharArray();
- chars[0] = updatedChar;
- return new String(chars, 0, chars.length);
- }
-
- /**
- * Extract the filename from the given Java resource path,
- * e.g. {@code "mypath/myfile.txt" -> "myfile.txt"}.
- * @param path the file path (may be {@code null})
- * @return the extracted filename, or {@code null} if none
- */
- public static String getFilename(String path) {
- if (path == null) {
- return null;
- }
-
- int separatorIndex = path.lastIndexOf(FOLDER_SEPARATOR);
- return (separatorIndex != -1 ? path.substring(separatorIndex + 1) : path);
- }
-
- /**
- * Extract the filename extension from the given Java resource path,
- *
- * @param path the file path (may be {@code null})
- * @return the extracted filename extension, or {@code null} if none
- */
- public static String getFilenameExtension(String path) {
- if (path == null) {
- return null;
- }
-
- int extIndex = path.lastIndexOf(EXTENSION_SEPARATOR);
- if (extIndex == -1) {
- return null;
- }
-
- int folderIndex = path.lastIndexOf(FOLDER_SEPARATOR);
- if (folderIndex > extIndex) {
- return null;
- }
-
- return path.substring(extIndex + 1);
- }
-
- /**
- * Strip the filename extension from the given Java resource path,
- *
- * @param path the file path
- * @return the path with stripped filename extension
- */
- public static String stripFilenameExtension(String path) {
- if (path == null) {
- return null;
- }
-
- int extIndex = path.lastIndexOf(EXTENSION_SEPARATOR);
- if (extIndex == -1) {
- return path;
- }
-
- int folderIndex = path.lastIndexOf(FOLDER_SEPARATOR);
- if (folderIndex > extIndex) {
- return path;
- }
-
- return path.substring(0, extIndex);
- }
-
- /**
- * Apply the given relative path to the given Java resource path,
- * assuming standard Java folder separation (i.e. "/" separators).
- * @param path the path to start from (usually a full file path)
- * @param relativePath the relative path to apply
- * (relative to the full file path above)
- * @return the full file path that results from applying the relative path
- */
- public static String applyRelativePath(String path, String relativePath) {
- int separatorIndex = path.lastIndexOf(FOLDER_SEPARATOR);
- if (separatorIndex != -1) {
- String newPath = path.substring(0, separatorIndex);
- if (!relativePath.startsWith(FOLDER_SEPARATOR)) {
- newPath += FOLDER_SEPARATOR;
- }
- return newPath + relativePath;
- }
- else {
- return relativePath;
- }
- }
-
- /**
- * Normalize the path by suppressing sequences like "path/.." and
- * inner simple dots.
- * The result is convenient for path comparison. For other uses,
- * notice that Windows separators ("\") are replaced by simple slashes.
- * @param path the original path
- * @return the normalized path
- */
- public static String cleanPath(String path) {
- if (path == null) {
- return null;
- }
- String pathToUse = replace(path, WINDOWS_FOLDER_SEPARATOR, FOLDER_SEPARATOR);
-
- // Strip prefix from path to analyze, to not treat it as part of the
- // first path element. This is necessary to correctly parse paths like
- // "file:core/../core/io/Resource.class", where the ".." should just
- // strip the first "core" directory while keeping the "file:" prefix.
- int prefixIndex = pathToUse.indexOf(":");
- String prefix = "";
- if (prefixIndex != -1) {
- prefix = pathToUse.substring(0, prefixIndex + 1);
- if (prefix.contains("/")) {
- prefix = "";
- }
- else {
- pathToUse = pathToUse.substring(prefixIndex + 1);
- }
- }
- if (pathToUse.startsWith(FOLDER_SEPARATOR)) {
- prefix = prefix + FOLDER_SEPARATOR;
- pathToUse = pathToUse.substring(1);
- }
-
- String[] pathArray = delimitedListToStringArray(pathToUse, FOLDER_SEPARATOR);
- List This is the inverse operation of {@link Locale#toString Locale's toString}.
- * @param localeString the locale {@code String}, following {@code Locale's}
- * {@code toString()} format ("en", "en_UK", etc);
- * also accepts spaces as separators, as an alternative to underscores
- * @return a corresponding {@code Locale} instance, or {@code null} if none
- * @throws IllegalArgumentException in case of an invalid locale specification
- */
- public static Locale parseLocaleString(String localeString) {
- String[] parts = tokenizeToStringArray(localeString, "_ ", false, false);
- String language = (parts.length > 0 ? parts[0] : "");
- String country = (parts.length > 1 ? parts[1] : "");
-
- validateLocalePart(language);
- validateLocalePart(country);
-
- String variant = "";
- if (parts.length > 2) {
- // There is definitely a variant, and it is everything after the country
- // code sans the separator between the country code and the variant.
- int endIndexOfCountryCode = localeString.indexOf(country, language.length()) + country.length();
- // Strip off any leading '_' and whitespace, what's left is the variant.
- variant = trimLeadingWhitespace(localeString.substring(endIndexOfCountryCode));
- if (variant.startsWith("_")) {
- variant = trimLeadingCharacter(variant, '_');
- }
- }
- return (language.length() > 0 ? new Locale(language, country, variant) : null);
- }
-
- private static void validateLocalePart(String localePart) {
- for (int i = 0; i < localePart.length(); i++) {
- char ch = localePart.charAt(i);
- if (ch != ' ' && ch != '_' && ch != '#' && !Character.isLetterOrDigit(ch)) {
- throw new IllegalArgumentException(
- "Locale part \"" + localePart + "\" contains invalid characters");
- }
- }
- }
-
- /**
- * Determine the RFC 3066 compliant language tag,
- * as used for the HTTP "Accept-Language" header.
- * @param locale the Locale to transform to a language tag
- * @return the RFC 3066 compliant language tag as {@code String}
- */
- public static String toLanguageTag(Locale locale) {
- return locale.getLanguage() + (hasText(locale.getCountry()) ? "-" + locale.getCountry() : "");
- }
-
- /**
- * Parse the given {@code timeZoneString} value into a {@link TimeZone}.
- * @param timeZoneString the time zone {@code String}, following {@link TimeZone#getTimeZone(String)}
- * but throwing {@link IllegalArgumentException} in case of an invalid time zone specification
- * @return a corresponding {@link TimeZone} instance
- * @throws IllegalArgumentException in case of an invalid time zone specification
- */
- public static TimeZone parseTimeZoneString(String timeZoneString) {
- TimeZone timeZone = TimeZone.getTimeZone(timeZoneString);
- if ("GMT".equals(timeZone.getID()) && !timeZoneString.startsWith("GMT")) {
- // We don't want that GMT fallback...
- throw new IllegalArgumentException("Invalid time zone specification '" + timeZoneString + "'");
- }
- return timeZone;
- }
-
-
- //---------------------------------------------------------------------
- // Convenience methods for working with String arrays
- //---------------------------------------------------------------------
-
- /**
- * Append the given {@code String} to the given {@code String} array,
- * returning a new array consisting of the input array contents plus
- * the given {@code String}.
- * @param array the array to append to (can be {@code null})
- * @param str the {@code String} to append
- * @return the new array (never {@code null})
- */
- public static String[] addStringToArray(String[] array, String str) {
- if (ObjectUtils.isEmpty(array)) {
- return new String[] {str};
- }
-
- String[] newArr = new String[array.length + 1];
- System.arraycopy(array, 0, newArr, 0, array.length);
- newArr[array.length] = str;
- return newArr;
- }
-
- /**
- * Concatenate the given {@code String} arrays into one,
- * with overlapping array elements included twice.
- * The order of elements in the original arrays is preserved.
- * @param array1 the first array (can be {@code null})
- * @param array2 the second array (can be {@code null})
- * @return the new array ({@code null} if both given arrays were {@code null})
- */
- public static String[] concatenateStringArrays(String[] array1, String[] array2) {
- if (ObjectUtils.isEmpty(array1)) {
- return array2;
- }
- if (ObjectUtils.isEmpty(array2)) {
- return array1;
- }
-
- String[] newArr = new String[array1.length + array2.length];
- System.arraycopy(array1, 0, newArr, 0, array1.length);
- System.arraycopy(array2, 0, newArr, array1.length, array2.length);
- return newArr;
- }
-
- /**
- * Merge the given {@code String} arrays into one, with overlapping
- * array elements only included once.
- * The order of elements in the original arrays is preserved
- * (with the exception of overlapping elements, which are only
- * included on their first occurrence).
- * @param array1 the first array (can be {@code null})
- * @param array2 the second array (can be {@code null})
- * @return the new array ({@code null} if both given arrays were {@code null})
- */
- public static String[] mergeStringArrays(String[] array1, String[] array2) {
- if (ObjectUtils.isEmpty(array1)) {
- return array2;
- }
- if (ObjectUtils.isEmpty(array2)) {
- return array1;
- }
-
- List The {@code Collection} must contain {@code String} elements only.
- * @param collection the {@code Collection} to copy
- * @return the {@code String} array
- */
- public static String[] toStringArray(Collection As of 4.2, it preserves the original order, as it uses a {@link LinkedHashSet}.
- * @param array the {@code String} array
- * @return an array without duplicates, in natural sort order
- */
- public static String[] removeDuplicateStrings(String[] array) {
- if (ObjectUtils.isEmpty(array)) {
- return array;
- }
-
- Set Will trim both the key and value before adding them to the
- * {@code Properties} instance.
- * @param array the array to process
- * @param delimiter to split each element using (typically the equals symbol)
- * @return a {@code Properties} instance representing the array contents,
- * or {@code null} if the array to process was {@code null} or empty
- */
- public static Properties splitArrayElementsIntoProperties(String[] array, String delimiter) {
- return splitArrayElementsIntoProperties(array, delimiter, null);
- }
-
- /**
- * Take an array of strings and split each element based on the given delimiter.
- * A {@code Properties} instance is then generated, with the left of the
- * delimiter providing the key, and the right of the delimiter providing the value.
- * Will trim both the key and value before adding them to the
- * {@code Properties} instance.
- * @param array the array to process
- * @param delimiter to split each element using (typically the equals symbol)
- * @param charsToDelete one or more characters to remove from each element
- * prior to attempting the split operation (typically the quotation mark
- * symbol), or {@code null} if no removal should occur
- * @return a {@code Properties} instance representing the array contents,
- * or {@code null} if the array to process was {@code null} or empty
- */
- public static Properties splitArrayElementsIntoProperties(
- String[] array, String delimiter, String charsToDelete) {
-
- if (ObjectUtils.isEmpty(array)) {
- return null;
- }
-
- Properties result = new Properties();
- for (String element : array) {
- if (charsToDelete != null) {
- element = deleteAny(element, charsToDelete);
- }
- String[] splittedElement = split(element, delimiter);
- if (splittedElement == null) {
- continue;
- }
- result.setProperty(splittedElement[0].trim(), splittedElement[1].trim());
- }
- return result;
- }
-
- /**
- * Tokenize the given {@code String} into a {@code String} array via a
- * {@link StringTokenizer}.
- * Trims tokens and omits empty tokens.
- * The given {@code delimiters} string can consist of any number of
- * delimiter characters. Each of those characters can be used to separate
- * tokens. A delimiter is always a single character; for multi-character
- * delimiters, consider using {@link #delimitedListToStringArray}.
- * @param str the {@code String} to tokenize
- * @param delimiters the delimiter characters, assembled as a {@code String}
- * (each of the characters is individually considered as a delimiter)
- * @return an array of the tokens
- * @see StringTokenizer
- * @see String#trim()
- * @see #delimitedListToStringArray
- */
- public static String[] tokenizeToStringArray(String str, String delimiters) {
- return tokenizeToStringArray(str, delimiters, true, true);
- }
-
- /**
- * Tokenize the given {@code String} into a {@code String} array via a
- * {@link StringTokenizer}.
- * The given {@code delimiters} string can consist of any number of
- * delimiter characters. Each of those characters can be used to separate
- * tokens. A delimiter is always a single character; for multi-character
- * delimiters, consider using {@link #delimitedListToStringArray}.
- * @param str the {@code String} to tokenize
- * @param delimiters the delimiter characters, assembled as a {@code String}
- * (each of the characters is individually considered as a delimiter)
- * @param trimTokens trim the tokens via {@link String#trim()}
- * @param ignoreEmptyTokens omit empty tokens from the result array
- * (only applies to tokens that are empty after trimming; StringTokenizer
- * will not consider subsequent delimiters as token in the first place).
- * @return an array of the tokens
- * @see StringTokenizer
- * @see String#trim()
- * @see #delimitedListToStringArray
- */
- public static String[] tokenizeToStringArray(
- String str, String delimiters, boolean trimTokens, boolean ignoreEmptyTokens) {
-
- if (str == null) {
- return null;
- }
-
- StringTokenizer st = new StringTokenizer(str, delimiters);
- List A single {@code delimiter} may consist of more than one character,
- * but it will still be considered as a single delimiter string, rather
- * than as bunch of potential delimiter characters, in contrast to
- * {@link #tokenizeToStringArray}.
- * @param str the input {@code String}
- * @param delimiter the delimiter between elements (this is a single delimiter,
- * rather than a bunch individual delimiter characters)
- * @return an array of the tokens in the list
- * @see #tokenizeToStringArray
- */
- public static String[] delimitedListToStringArray(String str, String delimiter) {
- return delimitedListToStringArray(str, delimiter, null);
- }
-
- /**
- * Take a {@code String} that is a delimited list and convert it into
- * a {@code String} array.
- * A single {@code delimiter} may consist of more than one character,
- * but it will still be considered as a single delimiter string, rather
- * than as bunch of potential delimiter characters, in contrast to
- * {@link #tokenizeToStringArray}.
- * @param str the input {@code String}
- * @param delimiter the delimiter between elements (this is a single delimiter,
- * rather than a bunch individual delimiter characters)
- * @param charsToDelete a set of characters to delete; useful for deleting unwanted
- * line breaks: e.g. "\r\n\f" will delete all new lines and line feeds in a {@code String}
- * @return an array of the tokens in the list
- * @see #tokenizeToStringArray
- */
- public static String[] delimitedListToStringArray(String str, String delimiter, String charsToDelete) {
- if (str == null) {
- return new String[0];
- }
- if (delimiter == null) {
- return new String[] {str};
- }
-
- List Note that this will suppress duplicates, and as of 4.2, the elements in
- * the returned set will preserve the original order in a {@link LinkedHashSet}.
- * @param str the input {@code String}
- * @return a set of {@code String} entries in the list
- * @see #removeDuplicateStrings(String[])
- */
- public static Set Useful for {@code toString()} implementations.
- * @param coll the {@code Collection} to convert
- * @param delim the delimiter to use (typically a ",")
- * @param prefix the {@code String} to start each element with
- * @param suffix the {@code String} to end each element with
- * @return the delimited {@code String}
- */
- public static String collectionToDelimitedString(Collection> coll, String delim, String prefix, String suffix) {
- if (CollectionUtils.isEmpty(coll)) {
- return "";
- }
-
- StringBuilder sb = new StringBuilder();
- Iterator> it = coll.iterator();
- while (it.hasNext()) {
- sb.append(prefix).append(it.next()).append(suffix);
- if (it.hasNext()) {
- sb.append(delim);
- }
- }
- return sb.toString();
- }
-
- /**
- * Convert a {@code Collection} into a delimited {@code String} (e.g. CSV).
- * Useful for {@code toString()} implementations.
- * @param coll the {@code Collection} to convert
- * @param delim the delimiter to use (typically a ",")
- * @return the delimited {@code String}
- */
- public static String collectionToDelimitedString(Collection> coll, String delim) {
- return collectionToDelimitedString(coll, delim, "", "");
- }
-
- /**
- * Convert a {@code Collection} into a delimited {@code String} (e.g., CSV).
- * Useful for {@code toString()} implementations.
- * @param coll the {@code Collection} to convert
- * @return the delimited {@code String}
- */
- public static String collectionToCommaDelimitedString(Collection> coll) {
- return collectionToDelimitedString(coll, ",");
- }
-
- /**
- * Convert a {@code String} array into a delimited {@code String} (e.g. CSV).
- * Useful for {@code toString()} implementations.
- * @param arr the array to display
- * @param delim the delimiter to use (typically a ",")
- * @return the delimited {@code String}
- */
- public static String arrayToDelimitedString(Object[] arr, String delim) {
- if (ObjectUtils.isEmpty(arr)) {
- return "";
- }
- if (arr.length == 1) {
- return ObjectUtils.nullSafeToString(arr[0]);
- }
-
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < arr.length; i++) {
- if (i > 0) {
- sb.append(delim);
- }
- sb.append(arr[i]);
- }
- return sb.toString();
- }
-
- /**
- * Convert a {@code String} array into a comma delimited {@code String}
- * (i.e., CSV).
- * Useful for {@code toString()} implementations.
- * @param arr the array to display
- * @return the delimited {@code String}
- */
- public static String arrayToCommaDelimitedString(Object[] arr) {
- return arrayToDelimitedString(arr, ",");
- }
-
- /**
- * Compares two CharSequences, returning {@code true} if they represent
- * equal sequences of characters. {@code null}s are handled without exceptions. Two {@code null}
- * references are considered to be equal. The comparison is case sensitive.
- *
- *
- * StringUtils.hasLength(null) = false
- * StringUtils.hasLength("") = false
- * StringUtils.hasLength(" ") = true
- * StringUtils.hasLength("Hello") = true
- *
- * @param str the {@code CharSequence} to check (may be {@code null})
- * @return {@code true} if the {@code CharSequence} is not {@code null} and has length
- * @see #hasText(String)
- */
- public static boolean hasLength(CharSequence str) {
- return (str != null && str.length() > 0);
- }
-
- /**
- * Check that the given {@code String} is neither {@code null} nor of length 0.
- *
- * StringUtils.hasText(null) = false
- * StringUtils.hasText("") = false
- * StringUtils.hasText(" ") = false
- * StringUtils.hasText("12345") = true
- * StringUtils.hasText(" 12345 ") = true
- *
- * @param str the {@code CharSequence} to check (may be {@code null})
- * @return {@code true} if the {@code CharSequence} is not {@code null},
- * its length is greater than 0, and it does not contain whitespace only
- * @see Character#isWhitespace
- */
- public static boolean hasText(CharSequence str) {
- return (hasLength(str) && containsText(str));
- }
-
- /**
- * Check whether the given {@code String} contains actual text.
- *
- * StringUtils.equals(null, null) = true
- * StringUtils.equals(null, "abc") = false
- * StringUtils.equals("abc", null) = false
- * StringUtils.equals("abc", "abc") = true
- * StringUtils.equals("abc", "ABC") = false
- *
- *
- * @see Object#equals(Object)
- * @param cs1 the first CharSequence, may be {@code null}
- * @param cs2 the second CharSequence, may be {@code null}
- * @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null}
- * @since 3.0 Changed signature from equals(String, String) to equals(CharSequence, CharSequence)
- */
- public static boolean equals(final CharSequence cs1, final CharSequence cs2) {
- if (cs1 == cs2) {
- return true;
- }
- if (cs1 == null || cs2 == null) {
- return false;
- }
- if (cs1.length() != cs2.length()) {
- return false;
- }
- if (cs1 instanceof String && cs2 instanceof String) {
- return cs1.equals(cs2);
- }
- return regionMatches(cs1, false, 0, cs2, 0, cs1.length());
- }
-
- /**
- * Green implementation of regionMatches.
- *
- * @param cs the {@code CharSequence} to be processed
- * @param ignoreCase whether or not to be case insensitive
- * @param thisStart the index to start on the {@code cs} CharSequence
- * @param substring the {@code CharSequence} to be looked for
- * @param start the index to start on the {@code substring} CharSequence
- * @param length character length of the region
- * @return whether the region matched
- */
- static boolean regionMatches(final CharSequence cs, final boolean ignoreCase, final int thisStart,
- final CharSequence substring, final int start, final int length) {
- if (cs instanceof String && substring instanceof String) {
- return ((String) cs).regionMatches(ignoreCase, thisStart, (String) substring, start, length);
- }
- int index1 = thisStart;
- int index2 = start;
- int tmpLen = length;
-
- // Extract these first so we detect NPEs the same as the java.lang.String version
- final int srcLen = cs.length() - thisStart;
- final int otherLen = substring.length() - start;
-
- // Check for invalid parameters
- if (thisStart < 0 || start < 0 || length < 0) {
- return false;
- }
-
- // Check that the regions are long enough
- if (srcLen < length || otherLen < length) {
- return false;
- }
-
- while (tmpLen-- > 0) {
- final char c1 = cs.charAt(index1++);
- final char c2 = substring.charAt(index2++);
-
- if (c1 == c2) {
- continue;
- }
-
- if (!ignoreCase) {
- return false;
- }
-
- // The same check as in String.regionMatches():
- if (Character.toUpperCase(c1) != Character.toUpperCase(c2)
- && Character.toLowerCase(c1) != Character.toLowerCase(c2)) {
- return false;
- }
- }
-
- return true;
- }
-
}