Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/ArrayUtils.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/ArrayUtils.java (.../ArrayUtils.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/ArrayUtils.java (.../ArrayUtils.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,58 +1,22 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
*
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- *
Operations on arrays, primitive arrays (like int[]
) and primitive wrapper arrays
- * (like Integer[]
).
Operations on arrays, primitive arrays (like int[]
) and
+ * primitive wrapper arrays (like Integer[]
).
This class tries to handle null
input gracefully.
* An exception will not be thrown for a null
* array input. However, an Object array that contains a null
* element may throw an exception. Each method documents its behaviour.
#ThreadSafe#
+ * @author Apache Software Foundation * @author Moritz Petersen * @author Fredrik Westermarck * @author Nikolay Metchev * @author Matthew Hawthorne * @author Tim O'Brien * @author Pete Gieser * @author Gary Gregory + * @author Ashwin S + * @author Maarten Coene * @since 2.0 * @version $Id$ */ @@ -161,15 +128,23 @@ public static final Character[] EMPTY_CHARACTER_OBJECT_ARRAY = new Character[0]; /** + * The index value when an element is not found in a list or array:-1
.
+ * This value is returned by methods in this class and can also be used in comparisons with values returned by
+ * various method from {@link java.util.List}.
+ */
+ public static final int INDEX_NOT_FOUND = -1;
+
+ /**
* ArrayUtils instances should NOT be constructed in standard programming.
* Instead, the class should be used as ArrayUtils.clone(new int[] {2})
.
This constructor is public to permit tools that require a JavaBean instance * to operate.
*/ public ArrayUtils() { + super(); } - + // Basic methods handling multi-dimensional arrays //----------------------------------------------------------------------- /** @@ -179,11 +154,11 @@ * multi-dimensional primitive arrays. * *The format is that of Java source code, for example {a,b}
.
null
* @return a String representation of the array, '{}' if null array input
*/
- public static String toString(final Object array) {
+ public static String toString(Object array) {
return toString(array, "{}");
}
@@ -194,12 +169,12 @@
* multi-dimensional primitive arrays.
*
* The format is that of Java source code, for example {a,b}
.
null
* @param stringIfNull the String to return if the array is null
* @return a String representation of the array
- */
- public static String toString(final Object array, final String stringIfNull) {
+ */
+ public static String toString(Object array, String stringIfNull) {
if (array == null) {
return stringIfNull;
}
@@ -208,27 +183,27 @@
/**
* Get a hashCode for an array handling multi-dimensional arrays correctly.
- * + * *Multi-dimensional primitive arrays are also handled correctly by this method.
- * + * * @param array the array to get a hashCode for, may benull
* @return a hashCode for the array, zero if null array input
*/
- public static int hashCode(final Object array) {
+ public static int hashCode(Object array) {
return new HashCodeBuilder().append(array).toHashCode();
}
/**
* Compares two arrays, using equals(), handling multi-dimensional arrays * correctly.
- * + * *Multi-dimensional primitive arrays are also handled correctly by this method.
- * - * @param array1 the array to get a hashCode for, may benull
- * @param array2 the array to get a hashCode for, may be null
+ *
+ * @param array1 the left hand array to compare, may be null
+ * @param array2 the right hand array to compare, may be null
* @return true
if the arrays are equal
*/
- public static boolean isEquals(final Object array1, final Object array2) {
+ public static boolean isEquals(Object array1, Object array2) {
return new EqualsBuilder().append(array1, array2).isEquals();
}
@@ -248,18 +223,18 @@
* {"GREEN", "#00FF00"},
* {"BLUE", "#0000FF"}});
*
- *
- * This method returns null
if null
array input.
This method returns null
for a null
input array.
null
* @return a Map
that was created from the array
* @throws IllegalArgumentException if one element of this Array is
* itself an Array containing less then two elements
* @throws IllegalArgumentException if the array contains elements other
* than {@link java.util.Map.Entry} and an Array
*/
- public static Map toMap(final Object[] array) {
+ public static Map toMap(Object[] array) {
if (array == null) {
return null;
}
@@ -272,13 +247,13 @@
} else if (object instanceof Object[]) {
Object[] entry = (Object[]) object;
if (entry.length < 2) {
- throw new IllegalArgumentException("Array element " + i + ", '"
+ throw new IllegalArgumentException("Array element " + i + ", '"
+ object
+ "', has a length less than 2");
}
map.put(entry[0], entry[1]);
} else {
- throw new IllegalArgumentException("Array element " + i + ", '"
+ throw new IllegalArgumentException("Array element " + i + ", '"
+ object
+ "', is neither of type Map.Entry nor an Array");
}
@@ -292,15 +267,15 @@
* Shallow clones an array returning a typecast result and handling
* null
.
The objecs in the array are not cloned, thus there is no special + *
The objects in the array are not cloned, thus there is no special * handling for multi-dimensional arrays.
- * - *This method returns null
if null
array input.
This method returns null
for a null
input array.
null
* @return the cloned array, null
if null
input
*/
- public static Object[] clone(final Object[] array) {
+ public static Object[] clone(Object[] array) {
if (array == null) {
return null;
}
@@ -311,12 +286,12 @@
* Clones an array returning a typecast result and handling
* null
.
This method returns null
if null
array input.
This method returns null
for a null
input array.
null
* @return the cloned array, null
if null
input
*/
- public static long[] clone(final long[] array) {
+ public static long[] clone(long[] array) {
if (array == null) {
return null;
}
@@ -327,8 +302,8 @@
* Clones an array returning a typecast result and handling
* null
.
This method returns null
if null
array input.
This method returns null
for a null
input array.
null
* @return the cloned array, null
if null
input
*/
@@ -343,12 +318,12 @@
* Clones an array returning a typecast result and handling
* null
.
This method returns null
if null
array input.
This method returns null
for a null
input array.
null
* @return the cloned array, null
if null
input
*/
- public static short[] clone(final short[] array) {
+ public static short[] clone(short[] array) {
if (array == null) {
return null;
}
@@ -359,12 +334,12 @@
* Clones an array returning a typecast result and handling
* null
.
This method returns null
if null
array input.
This method returns null
for a null
input array.
null
* @return the cloned array, null
if null
input
*/
- public static char[] clone(final char[] array) {
+ public static char[] clone(char[] array) {
if (array == null) {
return null;
}
@@ -375,12 +350,12 @@
* Clones an array returning a typecast result and handling
* null
.
This method returns null
if null
array input.
This method returns null
for a null
input array.
null
* @return the cloned array, null
if null
input
*/
- public static byte[] clone(final byte[] array) {
+ public static byte[] clone(byte[] array) {
if (array == null) {
return null;
}
@@ -391,12 +366,12 @@
* Clones an array returning a typecast result and handling
* null
.
This method returns null
if null
array input.
This method returns null
for a null
input array.
null
* @return the cloned array, null
if null
input
*/
- public static double[] clone(final double[] array) {
+ public static double[] clone(double[] array) {
if (array == null) {
return null;
}
@@ -407,12 +382,12 @@
* Clones an array returning a typecast result and handling
* null
.
This method returns null
if null
array input.
This method returns null
for a null
input array.
null
* @return the cloned array, null
if null
input
*/
- public static float[] clone(final float[] array) {
+ public static float[] clone(float[] array) {
if (array == null) {
return null;
}
@@ -423,32 +398,755 @@
* Clones an array returning a typecast result and handling
* null
.
This method returns null
if null
array input.
This method returns null
for a null
input array.
null
* @return the cloned array, null
if null
input
*/
- public static boolean[] clone(final boolean[] array) {
+ public static boolean[] clone(boolean[] array) {
if (array == null) {
return null;
}
return (boolean[]) array.clone();
}
+ // nullToEmpty
+ //-----------------------------------------------------------------------
+ /**
+ * Defensive programming technique to change a null
+ * reference to an empty one.
This method returns an empty array for a null
input array.
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty public static
references in this class.
null
or empty
+ * @return the same array, public static
empty array if null
or empty input
+ * @since 2.5
+ */
+ public static Object[] nullToEmpty(Object[] array) {
+ if (array == null || array.length == 0) {
+ return EMPTY_OBJECT_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ * Defensive programming technique to change a null
+ * reference to an empty one.
This method returns an empty array for a null
input array.
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty public static
references in this class.
null
or empty
+ * @return the same array, public static
empty array if null
or empty input
+ * @since 2.5
+ */
+ public static String[] nullToEmpty(String[] array) {
+ if (array == null || array.length == 0) {
+ return EMPTY_STRING_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ * Defensive programming technique to change a null
+ * reference to an empty one.
This method returns an empty array for a null
input array.
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty public static
references in this class.
null
or empty
+ * @return the same array, public static
empty array if null
or empty input
+ * @since 2.5
+ */
+ public static long[] nullToEmpty(long[] array) {
+ if (array == null || array.length == 0) {
+ return EMPTY_LONG_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ * Defensive programming technique to change a null
+ * reference to an empty one.
This method returns an empty array for a null
input array.
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty public static
references in this class.
null
or empty
+ * @return the same array, public static
empty array if null
or empty input
+ * @since 2.5
+ */
+ public static int[] nullToEmpty(int[] array) {
+ if (array == null || array.length == 0) {
+ return EMPTY_INT_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ * Defensive programming technique to change a null
+ * reference to an empty one.
This method returns an empty array for a null
input array.
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty public static
references in this class.
null
or empty
+ * @return the same array, public static
empty array if null
or empty input
+ * @since 2.5
+ */
+ public static short[] nullToEmpty(short[] array) {
+ if (array == null || array.length == 0) {
+ return EMPTY_SHORT_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ * Defensive programming technique to change a null
+ * reference to an empty one.
This method returns an empty array for a null
input array.
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty public static
references in this class.
null
or empty
+ * @return the same array, public static
empty array if null
or empty input
+ * @since 2.5
+ */
+ public static char[] nullToEmpty(char[] array) {
+ if (array == null || array.length == 0) {
+ return EMPTY_CHAR_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ * Defensive programming technique to change a null
+ * reference to an empty one.
This method returns an empty array for a null
input array.
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty public static
references in this class.
null
or empty
+ * @return the same array, public static
empty array if null
or empty input
+ * @since 2.5
+ */
+ public static byte[] nullToEmpty(byte[] array) {
+ if (array == null || array.length == 0) {
+ return EMPTY_BYTE_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ * Defensive programming technique to change a null
+ * reference to an empty one.
This method returns an empty array for a null
input array.
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty public static
references in this class.
null
or empty
+ * @return the same array, public static
empty array if null
or empty input
+ * @since 2.5
+ */
+ public static double[] nullToEmpty(double[] array) {
+ if (array == null || array.length == 0) {
+ return EMPTY_DOUBLE_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ * Defensive programming technique to change a null
+ * reference to an empty one.
This method returns an empty array for a null
input array.
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty public static
references in this class.
null
or empty
+ * @return the same array, public static
empty array if null
or empty input
+ * @since 2.5
+ */
+ public static float[] nullToEmpty(float[] array) {
+ if (array == null || array.length == 0) {
+ return EMPTY_FLOAT_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ * Defensive programming technique to change a null
+ * reference to an empty one.
This method returns an empty array for a null
input array.
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty public static
references in this class.
null
or empty
+ * @return the same array, public static
empty array if null
or empty input
+ * @since 2.5
+ */
+ public static boolean[] nullToEmpty(boolean[] array) {
+ if (array == null || array.length == 0) {
+ return EMPTY_BOOLEAN_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ * Defensive programming technique to change a null
+ * reference to an empty one.
This method returns an empty array for a null
input array.
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty public static
references in this class.
null
or empty
+ * @return the same array, public static
empty array if null
or empty input
+ * @since 2.5
+ */
+ public static Long[] nullToEmpty(Long[] array) {
+ if (array == null || array.length == 0) {
+ return EMPTY_LONG_OBJECT_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ * Defensive programming technique to change a null
+ * reference to an empty one.
This method returns an empty array for a null
input array.
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty public static
references in this class.
null
or empty
+ * @return the same array, public static
empty array if null
or empty input
+ * @since 2.5
+ */
+ public static Integer[] nullToEmpty(Integer[] array) {
+ if (array == null || array.length == 0) {
+ return EMPTY_INTEGER_OBJECT_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ * Defensive programming technique to change a null
+ * reference to an empty one.
This method returns an empty array for a null
input array.
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty public static
references in this class.
null
or empty
+ * @return the same array, public static
empty array if null
or empty input
+ * @since 2.5
+ */
+ public static Short[] nullToEmpty(Short[] array) {
+ if (array == null || array.length == 0) {
+ return EMPTY_SHORT_OBJECT_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ * Defensive programming technique to change a null
+ * reference to an empty one.
This method returns an empty array for a null
input array.
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty public static
references in this class.
null
or empty
+ * @return the same array, public static
empty array if null
or empty input
+ * @since 2.5
+ */
+ public static Character[] nullToEmpty(Character[] array) {
+ if (array == null || array.length == 0) {
+ return EMPTY_CHARACTER_OBJECT_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ * Defensive programming technique to change a null
+ * reference to an empty one.
This method returns an empty array for a null
input array.
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty public static
references in this class.
null
or empty
+ * @return the same array, public static
empty array if null
or empty input
+ * @since 2.5
+ */
+ public static Byte[] nullToEmpty(Byte[] array) {
+ if (array == null || array.length == 0) {
+ return EMPTY_BYTE_OBJECT_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ * Defensive programming technique to change a null
+ * reference to an empty one.
This method returns an empty array for a null
input array.
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty public static
references in this class.
null
or empty
+ * @return the same array, public static
empty array if null
or empty input
+ * @since 2.5
+ */
+ public static Double[] nullToEmpty(Double[] array) {
+ if (array == null || array.length == 0) {
+ return EMPTY_DOUBLE_OBJECT_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ * Defensive programming technique to change a null
+ * reference to an empty one.
This method returns an empty array for a null
input array.
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty public static
references in this class.
null
or empty
+ * @return the same array, public static
empty array if null
or empty input
+ * @since 2.5
+ */
+ public static Float[] nullToEmpty(Float[] array) {
+ if (array == null || array.length == 0) {
+ return EMPTY_FLOAT_OBJECT_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ * Defensive programming technique to change a null
+ * reference to an empty one.
This method returns an empty array for a null
input array.
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty public static
references in this class.
null
or empty
+ * @return the same array, public static
empty array if null
or empty input
+ * @since 2.5
+ */
+ public static Boolean[] nullToEmpty(Boolean[] array) {
+ if (array == null || array.length == 0) {
+ return EMPTY_BOOLEAN_OBJECT_ARRAY;
+ }
+ return array;
+ }
+
+ // Subarrays
+ //-----------------------------------------------------------------------
+ /**
+ * Produces a new array containing the elements between + * the start and end indices.
+ * + *The start index is inclusive, the end index exclusive. + * Null array input produces null output.
+ * + *The component type of the subarray is always the same as
+ * that of the input array. Thus, if the input is an array of type
+ * Date
, the following usage is envisaged:
+ * Date[] someDates = (Date[])ArrayUtils.subarray(allDates, 2, 5); + *+ * + * @param array the array + * @param startIndexInclusive the starting index. Undervalue (<0) + * is promoted to 0, overvalue (>array.length) results + * in an empty array. + * @param endIndexExclusive elements up to endIndex-1 are present in the + * returned subarray. Undervalue (< startIndex) produces + * empty array, overvalue (>array.length) is demoted to + * array length. + * @return a new array containing the elements between + * the start and end indices. + * @since 2.1 + */ + public static Object[] subarray(Object[] array, int startIndexInclusive, int endIndexExclusive) { + if (array == null) { + return null; + } + if (startIndexInclusive < 0) { + startIndexInclusive = 0; + } + if (endIndexExclusive > array.length) { + endIndexExclusive = array.length; + } + int newSize = endIndexExclusive - startIndexInclusive; + Class type = array.getClass().getComponentType(); + if (newSize <= 0) { + return (Object[]) Array.newInstance(type, 0); + } + Object[] subarray = (Object[]) Array.newInstance(type, newSize); + System.arraycopy(array, startIndexInclusive, subarray, 0, newSize); + return subarray; + } + + /** + *
Produces a new long
array containing the elements
+ * between the start and end indices.
The start index is inclusive, the end index exclusive. + * Null array input produces null output.
+ * + * @param array the array + * @param startIndexInclusive the starting index. Undervalue (<0) + * is promoted to 0, overvalue (>array.length) results + * in an empty array. + * @param endIndexExclusive elements up to endIndex-1 are present in the + * returned subarray. Undervalue (< startIndex) produces + * empty array, overvalue (>array.length) is demoted to + * array length. + * @return a new array containing the elements between + * the start and end indices. + * @since 2.1 + */ + public static long[] subarray(long[] array, int startIndexInclusive, int endIndexExclusive) { + if (array == null) { + return null; + } + if (startIndexInclusive < 0) { + startIndexInclusive = 0; + } + if (endIndexExclusive > array.length) { + endIndexExclusive = array.length; + } + int newSize = endIndexExclusive - startIndexInclusive; + if (newSize <= 0) { + return EMPTY_LONG_ARRAY; + } + + long[] subarray = new long[newSize]; + System.arraycopy(array, startIndexInclusive, subarray, 0, newSize); + return subarray; + } + + /** + *Produces a new int
array containing the elements
+ * between the start and end indices.
The start index is inclusive, the end index exclusive. + * Null array input produces null output.
+ * + * @param array the array + * @param startIndexInclusive the starting index. Undervalue (<0) + * is promoted to 0, overvalue (>array.length) results + * in an empty array. + * @param endIndexExclusive elements up to endIndex-1 are present in the + * returned subarray. Undervalue (< startIndex) produces + * empty array, overvalue (>array.length) is demoted to + * array length. + * @return a new array containing the elements between + * the start and end indices. + * @since 2.1 + */ + public static int[] subarray(int[] array, int startIndexInclusive, int endIndexExclusive) { + if (array == null) { + return null; + } + if (startIndexInclusive < 0) { + startIndexInclusive = 0; + } + if (endIndexExclusive > array.length) { + endIndexExclusive = array.length; + } + int newSize = endIndexExclusive - startIndexInclusive; + if (newSize <= 0) { + return EMPTY_INT_ARRAY; + } + + int[] subarray = new int[newSize]; + System.arraycopy(array, startIndexInclusive, subarray, 0, newSize); + return subarray; + } + + /** + *Produces a new short
array containing the elements
+ * between the start and end indices.
The start index is inclusive, the end index exclusive. + * Null array input produces null output.
+ * + * @param array the array + * @param startIndexInclusive the starting index. Undervalue (<0) + * is promoted to 0, overvalue (>array.length) results + * in an empty array. + * @param endIndexExclusive elements up to endIndex-1 are present in the + * returned subarray. Undervalue (< startIndex) produces + * empty array, overvalue (>array.length) is demoted to + * array length. + * @return a new array containing the elements between + * the start and end indices. + * @since 2.1 + */ + public static short[] subarray(short[] array, int startIndexInclusive, int endIndexExclusive) { + if (array == null) { + return null; + } + if (startIndexInclusive < 0) { + startIndexInclusive = 0; + } + if (endIndexExclusive > array.length) { + endIndexExclusive = array.length; + } + int newSize = endIndexExclusive - startIndexInclusive; + if (newSize <= 0) { + return EMPTY_SHORT_ARRAY; + } + + short[] subarray = new short[newSize]; + System.arraycopy(array, startIndexInclusive, subarray, 0, newSize); + return subarray; + } + + /** + *Produces a new char
array containing the elements
+ * between the start and end indices.
The start index is inclusive, the end index exclusive. + * Null array input produces null output.
+ * + * @param array the array + * @param startIndexInclusive the starting index. Undervalue (<0) + * is promoted to 0, overvalue (>array.length) results + * in an empty array. + * @param endIndexExclusive elements up to endIndex-1 are present in the + * returned subarray. Undervalue (< startIndex) produces + * empty array, overvalue (>array.length) is demoted to + * array length. + * @return a new array containing the elements between + * the start and end indices. + * @since 2.1 + */ + public static char[] subarray(char[] array, int startIndexInclusive, int endIndexExclusive) { + if (array == null) { + return null; + } + if (startIndexInclusive < 0) { + startIndexInclusive = 0; + } + if (endIndexExclusive > array.length) { + endIndexExclusive = array.length; + } + int newSize = endIndexExclusive - startIndexInclusive; + if (newSize <= 0) { + return EMPTY_CHAR_ARRAY; + } + + char[] subarray = new char[newSize]; + System.arraycopy(array, startIndexInclusive, subarray, 0, newSize); + return subarray; + } + + /** + *Produces a new byte
array containing the elements
+ * between the start and end indices.
The start index is inclusive, the end index exclusive. + * Null array input produces null output.
+ * + * @param array the array + * @param startIndexInclusive the starting index. Undervalue (<0) + * is promoted to 0, overvalue (>array.length) results + * in an empty array. + * @param endIndexExclusive elements up to endIndex-1 are present in the + * returned subarray. Undervalue (< startIndex) produces + * empty array, overvalue (>array.length) is demoted to + * array length. + * @return a new array containing the elements between + * the start and end indices. + * @since 2.1 + */ + public static byte[] subarray(byte[] array, int startIndexInclusive, int endIndexExclusive) { + if (array == null) { + return null; + } + if (startIndexInclusive < 0) { + startIndexInclusive = 0; + } + if (endIndexExclusive > array.length) { + endIndexExclusive = array.length; + } + int newSize = endIndexExclusive - startIndexInclusive; + if (newSize <= 0) { + return EMPTY_BYTE_ARRAY; + } + + byte[] subarray = new byte[newSize]; + System.arraycopy(array, startIndexInclusive, subarray, 0, newSize); + return subarray; + } + + /** + *Produces a new double
array containing the elements
+ * between the start and end indices.
The start index is inclusive, the end index exclusive. + * Null array input produces null output.
+ * + * @param array the array + * @param startIndexInclusive the starting index. Undervalue (<0) + * is promoted to 0, overvalue (>array.length) results + * in an empty array. + * @param endIndexExclusive elements up to endIndex-1 are present in the + * returned subarray. Undervalue (< startIndex) produces + * empty array, overvalue (>array.length) is demoted to + * array length. + * @return a new array containing the elements between + * the start and end indices. + * @since 2.1 + */ + public static double[] subarray(double[] array, int startIndexInclusive, int endIndexExclusive) { + if (array == null) { + return null; + } + if (startIndexInclusive < 0) { + startIndexInclusive = 0; + } + if (endIndexExclusive > array.length) { + endIndexExclusive = array.length; + } + int newSize = endIndexExclusive - startIndexInclusive; + if (newSize <= 0) { + return EMPTY_DOUBLE_ARRAY; + } + + double[] subarray = new double[newSize]; + System.arraycopy(array, startIndexInclusive, subarray, 0, newSize); + return subarray; + } + + /** + *Produces a new float
array containing the elements
+ * between the start and end indices.
The start index is inclusive, the end index exclusive. + * Null array input produces null output.
+ * + * @param array the array + * @param startIndexInclusive the starting index. Undervalue (<0) + * is promoted to 0, overvalue (>array.length) results + * in an empty array. + * @param endIndexExclusive elements up to endIndex-1 are present in the + * returned subarray. Undervalue (< startIndex) produces + * empty array, overvalue (>array.length) is demoted to + * array length. + * @return a new array containing the elements between + * the start and end indices. + * @since 2.1 + */ + public static float[] subarray(float[] array, int startIndexInclusive, int endIndexExclusive) { + if (array == null) { + return null; + } + if (startIndexInclusive < 0) { + startIndexInclusive = 0; + } + if (endIndexExclusive > array.length) { + endIndexExclusive = array.length; + } + int newSize = endIndexExclusive - startIndexInclusive; + if (newSize <= 0) { + return EMPTY_FLOAT_ARRAY; + } + + float[] subarray = new float[newSize]; + System.arraycopy(array, startIndexInclusive, subarray, 0, newSize); + return subarray; + } + + /** + *Produces a new boolean
array containing the elements
+ * between the start and end indices.
The start index is inclusive, the end index exclusive. + * Null array input produces null output.
+ * + * @param array the array + * @param startIndexInclusive the starting index. Undervalue (<0) + * is promoted to 0, overvalue (>array.length) results + * in an empty array. + * @param endIndexExclusive elements up to endIndex-1 are present in the + * returned subarray. Undervalue (< startIndex) produces + * empty array, overvalue (>array.length) is demoted to + * array length. + * @return a new array containing the elements between + * the start and end indices. + * @since 2.1 + */ + public static boolean[] subarray(boolean[] array, int startIndexInclusive, int endIndexExclusive) { + if (array == null) { + return null; + } + if (startIndexInclusive < 0) { + startIndexInclusive = 0; + } + if (endIndexExclusive > array.length) { + endIndexExclusive = array.length; + } + int newSize = endIndexExclusive - startIndexInclusive; + if (newSize <= 0) { + return EMPTY_BOOLEAN_ARRAY; + } + + boolean[] subarray = new boolean[newSize]; + System.arraycopy(array, startIndexInclusive, subarray, 0, newSize); + return subarray; + } + // Is same length //----------------------------------------------------------------------- /** *Checks whether two arrays are the same length, treating
* null
arrays as length 0
.
*
*
Any multi-dimensional aspects of the arrays are ignored.
- * + * * @param array1 the first array, may benull
* @param array2 the second array, may be null
* @return true
if length of arrays matches, treating
* null
as an empty array
- */
- public static boolean isSameLength(final Object[] array1, final Object[] array2) {
+ */
+ public static boolean isSameLength(Object[] array1, Object[] array2) {
if ((array1 == null && array2 != null && array2.length > 0) ||
(array2 == null && array1 != null && array1.length > 0) ||
(array1 != null && array2 != null && array1.length != array2.length)) {
@@ -460,13 +1158,13 @@
/**
* Checks whether two arrays are the same length, treating
* null
arrays as length 0
.
null
* @param array2 the second array, may be null
* @return true
if length of arrays matches, treating
* null
as an empty array
*/
- public static boolean isSameLength(final long[] array1, final long[] array2) {
+ public static boolean isSameLength(long[] array1, long[] array2) {
if ((array1 == null && array2 != null && array2.length > 0) ||
(array2 == null && array1 != null && array1.length > 0) ||
(array1 != null && array2 != null && array1.length != array2.length)) {
@@ -478,13 +1176,13 @@
/**
* Checks whether two arrays are the same length, treating
* null
arrays as length 0
.
null
* @param array2 the second array, may be null
* @return true
if length of arrays matches, treating
* null
as an empty array
*/
- public static boolean isSameLength(final int[] array1, final int[] array2) {
+ public static boolean isSameLength(int[] array1, int[] array2) {
if ((array1 == null && array2 != null && array2.length > 0) ||
(array2 == null && array1 != null && array1.length > 0) ||
(array1 != null && array2 != null && array1.length != array2.length)) {
@@ -496,13 +1194,13 @@
/**
* Checks whether two arrays are the same length, treating
* null
arrays as length 0
.
null
* @param array2 the second array, may be null
* @return true
if length of arrays matches, treating
* null
as an empty array
*/
- public static boolean isSameLength(final short[] array1, final short[] array2) {
+ public static boolean isSameLength(short[] array1, short[] array2) {
if ((array1 == null && array2 != null && array2.length > 0) ||
(array2 == null && array1 != null && array1.length > 0) ||
(array1 != null && array2 != null && array1.length != array2.length)) {
@@ -514,13 +1212,13 @@
/**
* Checks whether two arrays are the same length, treating
* null
arrays as length 0
.
null
* @param array2 the second array, may be null
* @return true
if length of arrays matches, treating
* null
as an empty array
*/
- public static boolean isSameLength(final char[] array1, final char[] array2) {
+ public static boolean isSameLength(char[] array1, char[] array2) {
if ((array1 == null && array2 != null && array2.length > 0) ||
(array2 == null && array1 != null && array1.length > 0) ||
(array1 != null && array2 != null && array1.length != array2.length)) {
@@ -532,13 +1230,13 @@
/**
* Checks whether two arrays are the same length, treating
* null
arrays as length 0
.
null
* @param array2 the second array, may be null
* @return true
if length of arrays matches, treating
* null
as an empty array
*/
- public static boolean isSameLength(final byte[] array1, final byte[] array2) {
+ public static boolean isSameLength(byte[] array1, byte[] array2) {
if ((array1 == null && array2 != null && array2.length > 0) ||
(array2 == null && array1 != null && array1.length > 0) ||
(array1 != null && array2 != null && array1.length != array2.length)) {
@@ -550,13 +1248,13 @@
/**
* Checks whether two arrays are the same length, treating
* null
arrays as length 0
.
null
* @param array2 the second array, may be null
* @return true
if length of arrays matches, treating
* null
as an empty array
*/
- public static boolean isSameLength(final double[] array1, final double[] array2) {
+ public static boolean isSameLength(double[] array1, double[] array2) {
if ((array1 == null && array2 != null && array2.length > 0) ||
(array2 == null && array1 != null && array1.length > 0) ||
(array1 != null && array2 != null && array1.length != array2.length)) {
@@ -568,13 +1266,13 @@
/**
* Checks whether two arrays are the same length, treating
* null
arrays as length 0
.
null
* @param array2 the second array, may be null
* @return true
if length of arrays matches, treating
* null
as an empty array
*/
- public static boolean isSameLength(final float[] array1, final float[] array2) {
+ public static boolean isSameLength(float[] array1, float[] array2) {
if ((array1 == null && array2 != null && array2.length > 0) ||
(array2 == null && array1 != null && array1.length > 0) ||
(array1 != null && array2 != null && array1.length != array2.length)) {
@@ -586,13 +1284,13 @@
/**
* Checks whether two arrays are the same length, treating
* null
arrays as length 0
.
null
* @param array2 the second array, may be null
* @return true
if length of arrays matches, treating
* null
as an empty array
*/
- public static boolean isSameLength(final boolean[] array1, final boolean[] array2) {
+ public static boolean isSameLength(boolean[] array1, boolean[] array2) {
if ((array1 == null && array2 != null && array2.length > 0) ||
(array2 == null && array1 != null && array1.length > 0) ||
(array1 != null && array2 != null && array1.length != array2.length)) {
@@ -601,16 +1299,44 @@
return true;
}
+ //-----------------------------------------------------------------------
/**
+ * Returns the length of the specified array.
+ * This method can deal with Object
arrays and with primitive arrays.
If the input array is null
, 0
is returned.
+ * ArrayUtils.getLength(null) = 0 + * ArrayUtils.getLength([]) = 0 + * ArrayUtils.getLength([null]) = 1 + * ArrayUtils.getLength([true, false]) = 2 + * ArrayUtils.getLength([1, 2, 3]) = 3 + * ArrayUtils.getLength(["a", "b", "c"]) = 3 + *+ * + * @param array the array to retrieve the length from, may be null + * @return The length of the array, or
0
if the array is null
+ * @throws IllegalArgumentException if the object arguement is not an array.
+ * @since 2.1
+ */
+ public static int getLength(Object array) {
+ if (array == null) {
+ return 0;
+ }
+ return Array.getLength(array);
+ }
+
+ /**
* Checks whether two arrays are the same type taking into account * multi-dimensional arrays.
- * + * * @param array1 the first array, must not benull
* @param array2 the second array, must not be null
* @return true
if type of arrays matches
* @throws IllegalArgumentException if either array is null
- */
- public static boolean isSameType(final Object array1, final Object array2) {
+ */
+ public static boolean isSameType(Object array1, Object array2) {
if (array1 == null || array2 == null) {
throw new IllegalArgumentException("The Array must not be null");
}
@@ -619,16 +1345,16 @@
// Reverse
//-----------------------------------------------------------------------
- /**
+ /**
* Reverses the order of the given array.
* *There is no special handling for multi-dimensional arrays.
* - *This method does nothing if null
array input.
This method does nothing for a null
input array.
null
*/
- public static void reverse(final Object[] array) {
+ public static void reverse(Object[] array) {
if (array == null) {
return;
}
@@ -646,12 +1372,12 @@
/**
* Reverses the order of the given array.
- * - *This method does nothing if null
array input.
This method does nothing for a null
input array.
null
*/
- public static void reverse(final long[] array) {
+ public static void reverse(long[] array) {
if (array == null) {
return;
}
@@ -669,12 +1395,12 @@
/**
* Reverses the order of the given array.
- * - *This method does nothing if null
array input.
This method does nothing for a null
input array.
null
*/
- public static void reverse(final int[] array) {
+ public static void reverse(int[] array) {
if (array == null) {
return;
}
@@ -692,12 +1418,12 @@
/**
* Reverses the order of the given array.
- * - *This method does nothing if null
array input.
This method does nothing for a null
input array.
null
*/
- public static void reverse(final short[] array) {
+ public static void reverse(short[] array) {
if (array == null) {
return;
}
@@ -715,12 +1441,12 @@
/**
* Reverses the order of the given array.
- * - *This method does nothing if null
array input.
This method does nothing for a null
input array.
null
*/
- public static void reverse(final char[] array) {
+ public static void reverse(char[] array) {
if (array == null) {
return;
}
@@ -738,12 +1464,12 @@
/**
* Reverses the order of the given array.
- * - *This method does nothing if null
array input.
This method does nothing for a null
input array.
null
*/
- public static void reverse(final byte[] array) {
+ public static void reverse(byte[] array) {
if (array == null) {
return;
}
@@ -761,12 +1487,12 @@
/**
* Reverses the order of the given array.
- * - *This method does nothing if null
array input.
This method does nothing for a null
input array.
null
*/
- public static void reverse(final double[] array) {
+ public static void reverse(double[] array) {
if (array == null) {
return;
}
@@ -784,12 +1510,12 @@
/**
* Reverses the order of the given array.
- * - *This method does nothing if null
array input.
This method does nothing for a null
input array.
null
*/
- public static void reverse(final float[] array) {
+ public static void reverse(float[] array) {
if (array == null) {
return;
}
@@ -807,12 +1533,12 @@
/**
* Reverses the order of the given array.
- * - *This method does nothing if null
array input.
This method does nothing for a null
input array.
null
*/
- public static void reverse(final boolean[] array) {
+ public static void reverse(boolean[] array) {
if (array == null) {
return;
}
@@ -830,40 +1556,40 @@
// IndexOf search
// ----------------------------------------------------------------------
-
+
// Object IndexOf
//-----------------------------------------------------------------------
/**
- * Find the index of the given object in the array.
+ *Finds the index of the given object in the array.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
null
* @param objectToFind the object to find, may be null
- * @return the index of the object within the array,
- * -1
if not found or null
array input
+ * @return the index of the object within the array,
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int indexOf(final Object[] array, final Object objectToFind) {
+ public static int indexOf(Object[] array, Object objectToFind) {
return indexOf(array, objectToFind, 0);
}
/**
- * Find the index of the given object in the array starting at the given index.
+ *Finds the index of the given object in the array starting at the given index.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
A negative startIndex is treated as zero. A startIndex larger than the array
- * length will return -1
.
-1
).
+ *
* @param array the array to search through for the object, may be null
* @param objectToFind the object to find, may be null
* @param startIndex the index to start searching at
* @return the index of the object within the array starting at the index,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int indexOf(final Object[] array, final Object objectToFind, int startIndex) {
+ public static int indexOf(Object[] array, Object objectToFind, int startIndex) {
if (array == null) {
- return -1;
+ return INDEX_NOT_FOUND;
}
if (startIndex < 0) {
startIndex = 0;
@@ -874,50 +1600,50 @@
return i;
}
}
- } else {
+ } else if (array.getClass().getComponentType().isInstance(objectToFind)) {
for (int i = startIndex; i < array.length; i++) {
if (objectToFind.equals(array[i])) {
return i;
}
}
}
- return -1;
+ return INDEX_NOT_FOUND;
}
/**
- * Find the last index of the given object within the array.
+ *Finds the last index of the given object within the array.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
null
* @param objectToFind the object to find, may be null
* @return the last index of the object within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int lastIndexOf(final Object[] array, final Object objectToFind) {
+ public static int lastIndexOf(Object[] array, Object objectToFind) {
return lastIndexOf(array, objectToFind, Integer.MAX_VALUE);
}
/**
- * Find the last index of the given object in the array starting at the given index.
+ *Finds the last index of the given object in the array starting at the given index.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
A negative startIndex will return -1
. A startIndex larger than
+ *
A negative startIndex will return {@link #INDEX_NOT_FOUND} (-1
). A startIndex larger than
* the array length will search from the end of the array.
null
* @param objectToFind the object to find, may be null
* @param startIndex the start index to travers backwards from
* @return the last index of the object within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int lastIndexOf(final Object[] array, final Object objectToFind, int startIndex) {
+ public static int lastIndexOf(Object[] array, Object objectToFind, int startIndex) {
if (array == null) {
- return -1;
+ return INDEX_NOT_FOUND;
}
if (startIndex < 0) {
- return -1;
+ return INDEX_NOT_FOUND;
} else if (startIndex >= array.length) {
startIndex = array.length - 1;
}
@@ -927,62 +1653,62 @@
return i;
}
}
- } else {
+ } else if (array.getClass().getComponentType().isInstance(objectToFind)) {
for (int i = startIndex; i >= 0; i--) {
if (objectToFind.equals(array[i])) {
return i;
}
}
}
- return -1;
+ return INDEX_NOT_FOUND;
}
/**
* Checks if the object is in the given array.
* *The method returns false
if a null
array is passed in.
true
if the array contains the object
*/
- public static boolean contains(final Object[] array, final Object objectToFind) {
- return (indexOf(array, objectToFind) != -1);
+ public static boolean contains(Object[] array, Object objectToFind) {
+ return indexOf(array, objectToFind) != INDEX_NOT_FOUND;
}
// long IndexOf
//-----------------------------------------------------------------------
/**
- * Find the index of the given value in the array.
+ *Finds the index of the given value in the array.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
null
* @param valueToFind the value to find
* @return the index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int indexOf(final long[] array, final long valueToFind) {
+ public static int indexOf(long[] array, long valueToFind) {
return indexOf(array, valueToFind, 0);
}
/**
- * Find the index of the given value in the array starting at the given index.
+ *Finds the index of the given value in the array starting at the given index.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
A negative startIndex is treated as zero. A startIndex larger than the array - * length will return -1.
- * + * length will return {@link #INDEX_NOT_FOUND} (-1
).
+ *
* @param array the array to search through for the object, may be null
* @param valueToFind the value to find
* @param startIndex the index to start searching at
* @return the index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int indexOf(final long[] array, final long valueToFind, int startIndex) {
+ public static int indexOf(long[] array, long valueToFind, int startIndex) {
if (array == null) {
- return -1;
+ return INDEX_NOT_FOUND;
}
if (startIndex < 0) {
startIndex = 0;
@@ -992,43 +1718,43 @@
return i;
}
}
- return -1;
+ return INDEX_NOT_FOUND;
}
/**
- * Find the last index of the given value within the array.
+ *Finds the last index of the given value within the array.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
null
* @param valueToFind the object to find
* @return the last index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int lastIndexOf(final long[] array, final long valueToFind) {
+ public static int lastIndexOf(long[] array, long valueToFind) {
return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
}
/**
- * Find the last index of the given value in the array starting at the given index.
+ *Finds the last index of the given value in the array starting at the given index.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
A negative startIndex will return -1. A startIndex larger than the array - * length will search from the end of the array.
- * + *A negative startIndex will return {@link #INDEX_NOT_FOUND} (-1
). A startIndex larger than the
+ * array length will search from the end of the array.
null
* @param valueToFind the value to find
* @param startIndex the start index to travers backwards from
* @return the last index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int lastIndexOf(final long[] array, final long valueToFind, int startIndex) {
+ public static int lastIndexOf(long[] array, long valueToFind, int startIndex) {
if (array == null) {
- return -1;
+ return INDEX_NOT_FOUND;
}
if (startIndex < 0) {
- return -1;
+ return INDEX_NOT_FOUND;
} else if (startIndex >= array.length) {
startIndex = array.length - 1;
}
@@ -1037,55 +1763,55 @@
return i;
}
}
- return -1;
+ return INDEX_NOT_FOUND;
}
/**
* Checks if the value is in the given array.
* *The method returns false
if a null
array is passed in.
true
if the array contains the object
*/
- public static boolean contains(final long[] array, final long valueToFind) {
- return (indexOf(array, valueToFind) != -1);
+ public static boolean contains(long[] array, long valueToFind) {
+ return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
}
// int IndexOf
//-----------------------------------------------------------------------
/**
- * Find the index of the given value in the array.
+ *Finds the index of the given value in the array.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
null
* @param valueToFind the value to find
* @return the index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int indexOf(final int[] array, final int valueToFind) {
+ public static int indexOf(int[] array, int valueToFind) {
return indexOf(array, valueToFind, 0);
}
/**
- * Find the index of the given value in the array starting at the given index.
+ *Finds the index of the given value in the array starting at the given index.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
A negative startIndex is treated as zero. A startIndex larger than the array - * length will return -1.
- * + * length will return {@link #INDEX_NOT_FOUND} (-1
).
+ *
* @param array the array to search through for the object, may be null
* @param valueToFind the value to find
* @param startIndex the index to start searching at
* @return the index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int indexOf(final int[] array, final int valueToFind, int startIndex) {
+ public static int indexOf(int[] array, int valueToFind, int startIndex) {
if (array == null) {
- return -1;
+ return INDEX_NOT_FOUND;
}
if (startIndex < 0) {
startIndex = 0;
@@ -1095,43 +1821,43 @@
return i;
}
}
- return -1;
+ return INDEX_NOT_FOUND;
}
/**
- * Find the last index of the given value within the array.
+ *Finds the last index of the given value within the array.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
null
* @param valueToFind the object to find
* @return the last index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int lastIndexOf(final int[] array, final int valueToFind) {
+ public static int lastIndexOf(int[] array, int valueToFind) {
return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
}
/**
- * Find the last index of the given value in the array starting at the given index.
+ *Finds the last index of the given value in the array starting at the given index.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
A negative startIndex will return -1. A startIndex larger than the array - * length will search from the end of the array.
- * + *A negative startIndex will return {@link #INDEX_NOT_FOUND} (-1
). A startIndex larger than the
+ * array length will search from the end of the array.
null
* @param valueToFind the value to find
* @param startIndex the start index to travers backwards from
* @return the last index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int lastIndexOf(final int[] array, final int valueToFind, int startIndex) {
+ public static int lastIndexOf(int[] array, int valueToFind, int startIndex) {
if (array == null) {
- return -1;
+ return INDEX_NOT_FOUND;
}
if (startIndex < 0) {
- return -1;
+ return INDEX_NOT_FOUND;
} else if (startIndex >= array.length) {
startIndex = array.length - 1;
}
@@ -1140,55 +1866,55 @@
return i;
}
}
- return -1;
+ return INDEX_NOT_FOUND;
}
/**
* Checks if the value is in the given array.
* *The method returns false
if a null
array is passed in.
true
if the array contains the object
*/
- public static boolean contains(final int[] array, final int valueToFind) {
- return (indexOf(array, valueToFind) != -1);
+ public static boolean contains(int[] array, int valueToFind) {
+ return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
}
// short IndexOf
//-----------------------------------------------------------------------
/**
- * Find the index of the given value in the array.
+ *Finds the index of the given value in the array.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
null
* @param valueToFind the value to find
* @return the index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int indexOf(final short[] array, final short valueToFind) {
+ public static int indexOf(short[] array, short valueToFind) {
return indexOf(array, valueToFind, 0);
}
/**
- * Find the index of the given value in the array starting at the given index.
+ *Finds the index of the given value in the array starting at the given index.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
A negative startIndex is treated as zero. A startIndex larger than the array - * length will return -1.
- * + * length will return {@link #INDEX_NOT_FOUND} (-1
).
+ *
* @param array the array to search through for the object, may be null
* @param valueToFind the value to find
* @param startIndex the index to start searching at
* @return the index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int indexOf(final short[] array, final short valueToFind, int startIndex) {
+ public static int indexOf(short[] array, short valueToFind, int startIndex) {
if (array == null) {
- return -1;
+ return INDEX_NOT_FOUND;
}
if (startIndex < 0) {
startIndex = 0;
@@ -1198,43 +1924,43 @@
return i;
}
}
- return -1;
+ return INDEX_NOT_FOUND;
}
/**
- * Find the last index of the given value within the array.
+ *Finds the last index of the given value within the array.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
null
* @param valueToFind the object to find
* @return the last index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int lastIndexOf(final short[] array, final short valueToFind) {
+ public static int lastIndexOf(short[] array, short valueToFind) {
return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
}
/**
- * Find the last index of the given value in the array starting at the given index.
+ *Finds the last index of the given value in the array starting at the given index.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
A negative startIndex will return -1. A startIndex larger than the array - * length will search from the end of the array.
- * + *A negative startIndex will return {@link #INDEX_NOT_FOUND} (-1
). A startIndex larger than the
+ * array length will search from the end of the array.
null
* @param valueToFind the value to find
* @param startIndex the start index to travers backwards from
* @return the last index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int lastIndexOf(final short[] array, final short valueToFind, int startIndex) {
+ public static int lastIndexOf(short[] array, short valueToFind, int startIndex) {
if (array == null) {
- return -1;
+ return INDEX_NOT_FOUND;
}
if (startIndex < 0) {
- return -1;
+ return INDEX_NOT_FOUND;
} else if (startIndex >= array.length) {
startIndex = array.length - 1;
}
@@ -1243,55 +1969,163 @@
return i;
}
}
- return -1;
+ return INDEX_NOT_FOUND;
}
/**
* Checks if the value is in the given array.
* *The method returns false
if a null
array is passed in.
true
if the array contains the object
*/
- public static boolean contains(final short[] array, final short valueToFind) {
- return (indexOf(array, valueToFind) != -1);
+ public static boolean contains(short[] array, short valueToFind) {
+ return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
}
+ // char IndexOf
+ //-----------------------------------------------------------------------
+ /**
+ * Finds the index of the given value in the array.
+ * + *This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
null
+ * @param valueToFind the value to find
+ * @return the index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
+ * @since 2.1
+ */
+ public static int indexOf(char[] array, char valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ /**
+ * Finds the index of the given value in the array starting at the given index.
+ * + *This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
A negative startIndex is treated as zero. A startIndex larger than the array
+ * length will return {@link #INDEX_NOT_FOUND} (-1
).
null
+ * @param valueToFind the value to find
+ * @param startIndex the index to start searching at
+ * @return the index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
+ * @since 2.1
+ */
+ public static int indexOf(char[] array, char valueToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ * Finds the last index of the given value within the array.
+ * + *This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
null
+ * @param valueToFind the object to find
+ * @return the last index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
+ * @since 2.1
+ */
+ public static int lastIndexOf(char[] array, char valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ /**
+ * Finds the last index of the given value in the array starting at the given index.
+ * + *This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
A negative startIndex will return {@link #INDEX_NOT_FOUND} (-1
). A startIndex larger than the
+ * array length will search from the end of the array.
null
+ * @param valueToFind the value to find
+ * @param startIndex the start index to travers backwards from
+ * @return the last index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
+ * @since 2.1
+ */
+ public static int lastIndexOf(char[] array, char valueToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ return INDEX_NOT_FOUND;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ * Checks if the value is in the given array.
+ * + *The method returns false
if a null
array is passed in.
true
if the array contains the object
+ * @since 2.1
+ */
+ public static boolean contains(char[] array, char valueToFind) {
+ return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
+ }
+
// byte IndexOf
//-----------------------------------------------------------------------
/**
- * Find the index of the given value in the array.
+ *Finds the index of the given value in the array.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
null
* @param valueToFind the value to find
* @return the index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int indexOf(final byte[] array, final byte valueToFind) {
+ public static int indexOf(byte[] array, byte valueToFind) {
return indexOf(array, valueToFind, 0);
}
/**
- * Find the index of the given value in the array starting at the given index.
+ *Finds the index of the given value in the array starting at the given index.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
A negative startIndex is treated as zero. A startIndex larger than the array - * length will return -1.
- * + * length will return {@link #INDEX_NOT_FOUND} (-1
).
+ *
* @param array the array to search through for the object, may be null
* @param valueToFind the value to find
* @param startIndex the index to start searching at
* @return the index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int indexOf(final byte[] array, final byte valueToFind, int startIndex) {
+ public static int indexOf(byte[] array, byte valueToFind, int startIndex) {
if (array == null) {
- return -1;
+ return INDEX_NOT_FOUND;
}
if (startIndex < 0) {
startIndex = 0;
@@ -1301,43 +2135,43 @@
return i;
}
}
- return -1;
+ return INDEX_NOT_FOUND;
}
/**
- * Find the last index of the given value within the array.
+ *Finds the last index of the given value within the array.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
null
* @param valueToFind the object to find
* @return the last index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int lastIndexOf(final byte[] array, final byte valueToFind) {
+ public static int lastIndexOf(byte[] array, byte valueToFind) {
return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
}
/**
- * Find the last index of the given value in the array starting at the given index.
+ *Finds the last index of the given value in the array starting at the given index.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
A negative startIndex will return -1. A startIndex larger than the array - * length will search from the end of the array.
- * + *A negative startIndex will return {@link #INDEX_NOT_FOUND} (-1
). A startIndex larger than the
+ * array length will search from the end of the array.
null
* @param valueToFind the value to find
* @param startIndex the start index to travers backwards from
* @return the last index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int lastIndexOf(final byte[] array, final byte valueToFind, int startIndex) {
+ public static int lastIndexOf(byte[] array, byte valueToFind, int startIndex) {
if (array == null) {
- return -1;
+ return INDEX_NOT_FOUND;
}
if (startIndex < 0) {
- return -1;
+ return INDEX_NOT_FOUND;
} else if (startIndex >= array.length) {
startIndex = array.length - 1;
}
@@ -1346,72 +2180,72 @@
return i;
}
}
- return -1;
+ return INDEX_NOT_FOUND;
}
/**
* Checks if the value is in the given array.
* *The method returns false
if a null
array is passed in.
true
if the array contains the object
*/
- public static boolean contains(final byte[] array, final byte valueToFind) {
- return (indexOf(array, valueToFind) != -1);
+ public static boolean contains(byte[] array, byte valueToFind) {
+ return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
}
// double IndexOf
//-----------------------------------------------------------------------
/**
- * Find the index of the given value in the array.
+ *Finds the index of the given value in the array.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
null
* @param valueToFind the value to find
* @return the index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int indexOf(final double[] array, final double valueToFind) {
+ public static int indexOf(double[] array, double valueToFind) {
return indexOf(array, valueToFind, 0);
}
/**
- * Find the index of the given value within a given tolerance in the array. + *
Finds the index of the given value within a given tolerance in the array. * This method will return the index of the first value which falls between the region * defined by valueToFind - tolerance and valueToFind + tolerance.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
null
* @param valueToFind the value to find
* @param tolerance tolerance of the search
* @return the index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int indexOf(final double[] array, final double valueToFind, final double tolerance) {
+ public static int indexOf(double[] array, double valueToFind, double tolerance) {
return indexOf(array, valueToFind, 0, tolerance);
}
/**
- * Find the index of the given value in the array starting at the given index.
+ *Finds the index of the given value in the array starting at the given index.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
A negative startIndex is treated as zero. A startIndex larger than the array - * length will return -1.
- * + * length will return {@link #INDEX_NOT_FOUND} (-1
).
+ *
* @param array the array to search through for the object, may be null
* @param valueToFind the value to find
* @param startIndex the index to start searching at
* @return the index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int indexOf(final double[] array, final double valueToFind, int startIndex) {
- if (array == null || array.length == 0) {
- return -1;
+ public static int indexOf(double[] array, double valueToFind, int startIndex) {
+ if (ArrayUtils.isEmpty(array)) {
+ return INDEX_NOT_FOUND;
}
if (startIndex < 0) {
startIndex = 0;
@@ -1421,29 +2255,29 @@
return i;
}
}
- return -1;
+ return INDEX_NOT_FOUND;
}
/**
- * Find the index of the given value in the array starting at the given index. + *
Finds the index of the given value in the array starting at the given index. * This method will return the index of the first value which falls between the region * defined by valueToFind - tolerance and valueToFind + tolerance.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
A negative startIndex is treated as zero. A startIndex larger than the array - * length will return -1.
- * + * length will return {@link #INDEX_NOT_FOUND} (-1
).
+ *
* @param array the array to search through for the object, may be null
* @param valueToFind the value to find
* @param startIndex the index to start searching at
* @param tolerance tolerance of the search
* @return the index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int indexOf(final double[] array, final double valueToFind, int startIndex, double tolerance) {
- if (array == null || array.length == 0) {
- return -1;
+ public static int indexOf(double[] array, double valueToFind, int startIndex, double tolerance) {
+ if (ArrayUtils.isEmpty(array)) {
+ return INDEX_NOT_FOUND;
}
if (startIndex < 0) {
startIndex = 0;
@@ -1455,60 +2289,60 @@
return i;
}
}
- return -1;
+ return INDEX_NOT_FOUND;
}
/**
- * Find the last index of the given value within the array.
+ *Finds the last index of the given value within the array.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
null
* @param valueToFind the object to find
* @return the last index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int lastIndexOf(final double[] array, final double valueToFind) {
+ public static int lastIndexOf(double[] array, double valueToFind) {
return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
}
/**
- * Find the last index of the given value within a given tolerance in the array. + *
Finds the last index of the given value within a given tolerance in the array. * This method will return the index of the last value which falls between the region * defined by valueToFind - tolerance and valueToFind + tolerance.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
null
* @param valueToFind the value to find
* @param tolerance tolerance of the search
* @return the index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int lastIndexOf(final double[] array, final double valueToFind, final double tolerance) {
+ public static int lastIndexOf(double[] array, double valueToFind, double tolerance) {
return lastIndexOf(array, valueToFind, Integer.MAX_VALUE, tolerance);
}
/**
- * Find the last index of the given value in the array starting at the given index.
+ *Finds the last index of the given value in the array starting at the given index.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
A negative startIndex will return -1. A startIndex larger than the array - * length will search from the end of the array.
- * + *A negative startIndex will return {@link #INDEX_NOT_FOUND} (-1
). A startIndex larger than the
+ * array length will search from the end of the array.
null
* @param valueToFind the value to find
* @param startIndex the start index to travers backwards from
* @return the last index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int lastIndexOf(final double[] array, final double valueToFind, int startIndex) {
- if (array == null || array.length == 0) {
- return -1;
+ public static int lastIndexOf(double[] array, double valueToFind, int startIndex) {
+ if (ArrayUtils.isEmpty(array)) {
+ return INDEX_NOT_FOUND;
}
if (startIndex < 0) {
- return -1;
+ return INDEX_NOT_FOUND;
} else if (startIndex >= array.length) {
startIndex = array.length - 1;
}
@@ -1517,32 +2351,32 @@
return i;
}
}
- return -1;
+ return INDEX_NOT_FOUND;
}
/**
- * Find the last index of the given value in the array starting at the given index. + *
Finds the last index of the given value in the array starting at the given index. * This method will return the index of the last value which falls between the region * defined by valueToFind - tolerance and valueToFind + tolerance.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
A negative startIndex will return -1. A startIndex larger than the array - * length will search from the end of the array.
- * + *A negative startIndex will return {@link #INDEX_NOT_FOUND} (-1
). A startIndex larger than the
+ * array length will search from the end of the array.
null
* @param valueToFind the value to find
* @param startIndex the start index to travers backwards from
* @param tolerance search for value within plus/minus this amount
* @return the last index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int lastIndexOf(final double[] array, final double valueToFind, int startIndex, double tolerance) {
- if (array == null || array.length == 0) {
- return -1;
+ public static int lastIndexOf(double[] array, double valueToFind, int startIndex, double tolerance) {
+ if (ArrayUtils.isEmpty(array)) {
+ return INDEX_NOT_FOUND;
}
if (startIndex < 0) {
- return -1;
+ return INDEX_NOT_FOUND;
} else if (startIndex >= array.length) {
startIndex = array.length - 1;
}
@@ -1553,25 +2387,25 @@
return i;
}
}
- return -1;
+ return INDEX_NOT_FOUND;
}
/**
* Checks if the value is in the given array.
* *The method returns false
if a null
array is passed in.
true
if the array contains the object
*/
- public static boolean contains(final double[] array, final double valueToFind) {
- return (indexOf(array, valueToFind) != -1);
+ public static boolean contains(double[] array, double valueToFind) {
+ return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
}
/**
* Checks if a value falling within the given tolerance is in the - * given array. If the array contains a value within the inclusive range + * given array. If the array contains a value within the inclusive range * defined by (value - tolerance) to (value + tolerance).
* *The method returns false
if a null
array
@@ -1582,43 +2416,43 @@
* @param tolerance the array contains the tolerance of the search
* @return true if value falling within tolerance is in array
*/
- public static boolean contains(final double[] array, final double valueToFind, final double tolerance) {
- return (indexOf(array, valueToFind, 0, tolerance) != -1);
+ public static boolean contains(double[] array, double valueToFind, double tolerance) {
+ return indexOf(array, valueToFind, 0, tolerance) != INDEX_NOT_FOUND;
}
// float IndexOf
//-----------------------------------------------------------------------
/**
- *
Find the index of the given value in the array.
+ *Finds the index of the given value in the array.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
null
* @param valueToFind the value to find
* @return the index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int indexOf(final float[] array, final float valueToFind) {
+ public static int indexOf(float[] array, float valueToFind) {
return indexOf(array, valueToFind, 0);
}
/**
- * Find the index of the given value in the array starting at the given index.
+ *Finds the index of the given value in the array starting at the given index.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
A negative startIndex is treated as zero. A startIndex larger than the array - * length will return -1.
- * + * length will return {@link #INDEX_NOT_FOUND} (-1
).
+ *
* @param array the array to search through for the object, may be null
* @param valueToFind the value to find
* @param startIndex the index to start searching at
* @return the index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int indexOf(final float[] array, final float valueToFind, int startIndex) {
- if (array == null || array.length == 0) {
- return -1;
+ public static int indexOf(float[] array, float valueToFind, int startIndex) {
+ if (ArrayUtils.isEmpty(array)) {
+ return INDEX_NOT_FOUND;
}
if (startIndex < 0) {
startIndex = 0;
@@ -1628,43 +2462,43 @@
return i;
}
}
- return -1;
+ return INDEX_NOT_FOUND;
}
/**
- * Find the last index of the given value within the array.
+ *Finds the last index of the given value within the array.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
null
* @param valueToFind the object to find
* @return the last index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int lastIndexOf(final float[] array, final float valueToFind) {
+ public static int lastIndexOf(float[] array, float valueToFind) {
return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
}
/**
- * Find the last index of the given value in the array starting at the given index.
+ *Finds the last index of the given value in the array starting at the given index.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
A negative startIndex will return -1. A startIndex larger than the array - * length will search from the end of the array.
- * + *A negative startIndex will return {@link #INDEX_NOT_FOUND} (-1
). A startIndex larger than the
+ * array length will search from the end of the array.
null
* @param valueToFind the value to find
* @param startIndex the start index to travers backwards from
* @return the last index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int lastIndexOf(final float[] array, final float valueToFind, int startIndex) {
- if (array == null || array.length == 0) {
- return -1;
+ public static int lastIndexOf(float[] array, float valueToFind, int startIndex) {
+ if (ArrayUtils.isEmpty(array)) {
+ return INDEX_NOT_FOUND;
}
if (startIndex < 0) {
- return -1;
+ return INDEX_NOT_FOUND;
} else if (startIndex >= array.length) {
startIndex = array.length - 1;
}
@@ -1673,55 +2507,56 @@
return i;
}
}
- return -1;
+ return INDEX_NOT_FOUND;
}
/**
* Checks if the value is in the given array.
* *The method returns false
if a null
array is passed in.
true
if the array contains the object
*/
- public static boolean contains(final float[] array, final float valueToFind) {
- return (indexOf(array, valueToFind) != -1);
+ public static boolean contains(float[] array, float valueToFind) {
+ return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
}
// boolean IndexOf
//-----------------------------------------------------------------------
/**
- * Find the index of the given value in the array.
+ *Finds the index of the given value in the array.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
null
* @param valueToFind the value to find
* @return the index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int indexOf(final boolean[] array, final boolean valueToFind) {
+ public static int indexOf(boolean[] array, boolean valueToFind) {
return indexOf(array, valueToFind, 0);
}
/**
- * Find the index of the given value in the array starting at the given index.
+ *Finds the index of the given value in the array starting at the given index.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
A negative startIndex is treated as zero. A startIndex larger than the array - * length will return -1.
- * + * length will return {@link #INDEX_NOT_FOUND} (-1
).
+ *
* @param array the array to search through for the object, may be null
* @param valueToFind the value to find
* @param startIndex the index to start searching at
* @return the index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
+ * array input
*/
- public static int indexOf(final boolean[] array, final boolean valueToFind, int startIndex) {
- if (array == null || array.length == 0) {
- return -1;
+ public static int indexOf(boolean[] array, boolean valueToFind, int startIndex) {
+ if (ArrayUtils.isEmpty(array)) {
+ return INDEX_NOT_FOUND;
}
if (startIndex < 0) {
startIndex = 0;
@@ -1731,43 +2566,44 @@
return i;
}
}
- return -1;
+ return INDEX_NOT_FOUND;
}
/**
- * Find the last index of the given value within the array.
+ *Finds the last index of the given value within the array.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) if
+ * null
array input.
null
* @param valueToFind the object to find
* @return the last index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int lastIndexOf(final boolean[] array, final boolean valueToFind) {
+ public static int lastIndexOf(boolean[] array, boolean valueToFind) {
return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
}
/**
- * Find the last index of the given value in the array starting at the given index.
+ *Finds the last index of the given value in the array starting at the given index.
* - *This method returns -1
if null
array input.
This method returns {@link #INDEX_NOT_FOUND} (-1
) for a null
input array.
A negative startIndex will return -1. A startIndex larger than the array - * length will search from the end of the array.
- * + *A negative startIndex will return {@link #INDEX_NOT_FOUND} (-1
). A startIndex larger than
+ * the array length will search from the end of the array.
null
* @param valueToFind the value to find
* @param startIndex the start index to travers backwards from
* @return the last index of the value within the array,
- * -1
if not found or null
array input
+ * {@link #INDEX_NOT_FOUND} (-1
) if not found or null
array input
*/
- public static int lastIndexOf(final boolean[] array, final boolean valueToFind, int startIndex) {
- if (array == null || array.length == 0) {
- return -1;
+ public static int lastIndexOf(boolean[] array, boolean valueToFind, int startIndex) {
+ if (ArrayUtils.isEmpty(array)) {
+ return INDEX_NOT_FOUND;
}
if (startIndex < 0) {
- return -1;
+ return INDEX_NOT_FOUND;
} else if (startIndex >= array.length) {
startIndex = array.length - 1;
}
@@ -1776,37 +2612,105 @@
return i;
}
}
- return -1;
+ return INDEX_NOT_FOUND;
}
/**
* Checks if the value is in the given array.
* *The method returns false
if a null
array is passed in.
true
if the array contains the object
*/
- public static boolean contains(final boolean[] array, final boolean valueToFind) {
- return (indexOf(array, valueToFind) != -1);
+ public static boolean contains(boolean[] array, boolean valueToFind) {
+ return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
}
// Primitive/Object array converters
// ----------------------------------------------------------------------
-
+
+ // Character array converters
+ // ----------------------------------------------------------------------
+ /**
+ * Converts an array of object Characters to primitives.
+ * + *This method returns null
for a null
input array.
Character
array, may be null
+ * @return a char
array, null
if null array input
+ * @throws NullPointerException if array content is null
+ */
+ public static char[] toPrimitive(Character[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_CHAR_ARRAY;
+ }
+ final char[] result = new char[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = array[i].charValue();
+ }
+ return result;
+ }
+
+ /**
+ * Converts an array of object Character to primitives handling null
.
This method returns null
for a null
input array.
Character
array, may be null
+ * @param valueForNull the value to insert if null
found
+ * @return a char
array, null
if null array input
+ */
+ public static char[] toPrimitive(Character[] array, char valueForNull) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_CHAR_ARRAY;
+ }
+ final char[] result = new char[array.length];
+ for (int i = 0; i < array.length; i++) {
+ Character b = array[i];
+ result[i] = (b == null ? valueForNull : b.charValue());
+ }
+ return result;
+ }
+
+ /**
+ * Converts an array of primitive chars to objects.
+ * + *This method returns null
for a null
input array.
char
array
+ * @return a Character
array, null
if null array input
+ */
+ public static Character[] toObject(char[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_CHARACTER_OBJECT_ARRAY;
+ }
+ final Character[] result = new Character[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = new Character(array[i]);
+ }
+ return result;
+ }
+
// Long array converters
// ----------------------------------------------------------------------
/**
* Converts an array of object Longs to primitives.
* - *This method returns null
if null
array input.
This method returns null
for a null
input array.
Long
array, may be null
* @return a long
array, null
if null array input
* @throws NullPointerException if array content is null
*/
- public static long[] toPrimitive(final Long[] array) {
+ public static long[] toPrimitive(Long[] array) {
if (array == null) {
return null;
} else if (array.length == 0) {
@@ -1818,17 +2722,17 @@
}
return result;
}
-
+
/**
* Converts an array of object Long to primitives handling null
.
This method returns null
if null
array input.
This method returns null
for a null
input array.
Long
array, may be null
* @param valueForNull the value to insert if null
found
* @return a long
array, null
if null array input
*/
- public static long[] toPrimitive(final Long[] array, final long valueForNull) {
+ public static long[] toPrimitive(Long[] array, long valueForNull) {
if (array == null) {
return null;
} else if (array.length == 0) {
@@ -1841,16 +2745,16 @@
}
return result;
}
-
+
/**
* Converts an array of primitive longs to objects.
* - *This method returns null
if null
array input.
This method returns null
for a null
input array.
long
array
* @return a Long
array, null
if null array input
*/
- public static Long[] toObject(final long[] array) {
+ public static Long[] toObject(long[] array) {
if (array == null) {
return null;
} else if (array.length == 0) {
@@ -1868,13 +2772,13 @@
/**
* Converts an array of object Integers to primitives.
* - *This method returns null
if null
array input.
This method returns null
for a null
input array.
Integer
array, may be null
* @return an int
array, null
if null array input
* @throws NullPointerException if array content is null
*/
- public static int[] toPrimitive(final Integer[] array) {
+ public static int[] toPrimitive(Integer[] array) {
if (array == null) {
return null;
} else if (array.length == 0) {
@@ -1889,14 +2793,14 @@
/**
* Converts an array of object Integer to primitives handling null
.
This method returns null
if null
array input.
This method returns null
for a null
input array.
Integer
array, may be null
* @param valueForNull the value to insert if null
found
* @return an int
array, null
if null array input
*/
- public static int[] toPrimitive(final Integer[] array, final int valueForNull) {
+ public static int[] toPrimitive(Integer[] array, int valueForNull) {
if (array == null) {
return null;
} else if (array.length == 0) {
@@ -1913,12 +2817,12 @@
/**
* Converts an array of primitive ints to objects.
* - *This method returns null
if null
array input.
This method returns null
for a null
input array.
int
array
* @return an Integer
array, null
if null array input
*/
- public static Integer[] toObject(final int[] array) {
+ public static Integer[] toObject(int[] array) {
if (array == null) {
return null;
} else if (array.length == 0) {
@@ -1930,19 +2834,19 @@
}
return result;
}
-
+
// Short array converters
// ----------------------------------------------------------------------
/**
* Converts an array of object Shorts to primitives.
* - *This method returns null
if null
array input.
This method returns null
for a null
input array.
Short
array, may be null
* @return a byte
array, null
if null array input
* @throws NullPointerException if array content is null
*/
- public static short[] toPrimitive(final Short[] array) {
+ public static short[] toPrimitive(Short[] array) {
if (array == null) {
return null;
} else if (array.length == 0) {
@@ -1957,14 +2861,14 @@
/**
* Converts an array of object Short to primitives handling null
.
This method returns null
if null
array input.
This method returns null
for a null
input array.
Short
array, may be null
* @param valueForNull the value to insert if null
found
* @return a byte
array, null
if null array input
*/
- public static short[] toPrimitive(final Short[] array, final short valueForNull) {
+ public static short[] toPrimitive(Short[] array, short valueForNull) {
if (array == null) {
return null;
} else if (array.length == 0) {
@@ -1981,12 +2885,12 @@
/**
* Converts an array of primitive shorts to objects.
* - *This method returns null
if null
array input.
This method returns null
for a null
input array.
short
array
* @return a Short
array, null
if null array input
*/
- public static Short[] toObject(final short[] array) {
+ public static Short[] toObject(short[] array) {
if (array == null) {
return null;
} else if (array.length == 0) {
@@ -1997,20 +2901,20 @@
result[i] = new Short(array[i]);
}
return result;
- }
+ }
// Byte array converters
// ----------------------------------------------------------------------
/**
* Converts an array of object Bytes to primitives.
* - *This method returns null
if null
array input.
This method returns null
for a null
input array.
Byte
array, may be null
* @return a byte
array, null
if null array input
* @throws NullPointerException if array content is null
*/
- public static byte[] toPrimitive(final Byte[] array) {
+ public static byte[] toPrimitive(Byte[] array) {
if (array == null) {
return null;
} else if (array.length == 0) {
@@ -2025,14 +2929,14 @@
/**
* Converts an array of object Bytes to primitives handling null
.
This method returns null
if null
array input.
This method returns null
for a null
input array.
Byte
array, may be null
* @param valueForNull the value to insert if null
found
* @return a byte
array, null
if null array input
*/
- public static byte[] toPrimitive(final Byte[] array, final byte valueForNull) {
+ public static byte[] toPrimitive(Byte[] array, byte valueForNull) {
if (array == null) {
return null;
} else if (array.length == 0) {
@@ -2049,12 +2953,12 @@
/**
* Converts an array of primitive bytes to objects.
* - *This method returns null
if null
array input.
This method returns null
for a null
input array.
byte
array
* @return a Byte
array, null
if null array input
*/
- public static Byte[] toObject(final byte[] array) {
+ public static Byte[] toObject(byte[] array) {
if (array == null) {
return null;
} else if (array.length == 0) {
@@ -2065,20 +2969,20 @@
result[i] = new Byte(array[i]);
}
return result;
- }
-
+ }
+
// Double array converters
// ----------------------------------------------------------------------
/**
* Converts an array of object Doubles to primitives.
* - *This method returns null
if null
array input.
This method returns null
for a null
input array.
Double
array, may be null
* @return a double
array, null
if null array input
* @throws NullPointerException if array content is null
*/
- public static double[] toPrimitive(final Double[] array) {
+ public static double[] toPrimitive(Double[] array) {
if (array == null) {
return null;
} else if (array.length == 0) {
@@ -2093,14 +2997,14 @@
/**
* Converts an array of object Doubles to primitives handling null
.
This method returns null
if null
array input.
This method returns null
for a null
input array.
Double
array, may be null
* @param valueForNull the value to insert if null
found
* @return a double
array, null
if null array input
*/
- public static double[] toPrimitive(final Double[] array, final double valueForNull) {
+ public static double[] toPrimitive(Double[] array, double valueForNull) {
if (array == null) {
return null;
} else if (array.length == 0) {
@@ -2117,12 +3021,12 @@
/**
* Converts an array of primitive doubles to objects.
* - *This method returns null
if null
array input.
This method returns null
for a null
input array.
double
array
* @return a Double
array, null
if null array input
*/
- public static Double[] toObject(final double[] array) {
+ public static Double[] toObject(double[] array) {
if (array == null) {
return null;
} else if (array.length == 0) {
@@ -2140,13 +3044,13 @@
/**
* Converts an array of object Floats to primitives.
* - *This method returns null
if null
array input.
This method returns null
for a null
input array.
Float
array, may be null
* @return a float
array, null
if null array input
* @throws NullPointerException if array content is null
*/
- public static float[] toPrimitive(final Float[] array) {
+ public static float[] toPrimitive(Float[] array) {
if (array == null) {
return null;
} else if (array.length == 0) {
@@ -2161,14 +3065,14 @@
/**
* Converts an array of object Floats to primitives handling null
.
This method returns null
if null
array input.
This method returns null
for a null
input array.
Float
array, may be null
* @param valueForNull the value to insert if null
found
* @return a float
array, null
if null array input
*/
- public static float[] toPrimitive(final Float[] array, final float valueForNull) {
+ public static float[] toPrimitive(Float[] array, float valueForNull) {
if (array == null) {
return null;
} else if (array.length == 0) {
@@ -2185,12 +3089,12 @@
/**
* Converts an array of primitive floats to objects.
* - *This method returns null
if null
array input.
This method returns null
for a null
input array.
float
array
* @return a Float
array, null
if null array input
*/
- public static Float[] toObject(final float[] array) {
+ public static Float[] toObject(float[] array) {
if (array == null) {
return null;
} else if (array.length == 0) {
@@ -2208,13 +3112,13 @@
/**
* Converts an array of object Booleans to primitives.
* - *This method returns null
if null
array input.
This method returns null
for a null
input array.
Boolean
array, may be null
* @return a boolean
array, null
if null array input
* @throws NullPointerException if array content is null
*/
- public static boolean[] toPrimitive(final Boolean[] array) {
+ public static boolean[] toPrimitive(Boolean[] array) {
if (array == null) {
return null;
} else if (array.length == 0) {
@@ -2229,14 +3133,14 @@
/**
* Converts an array of object Booleans to primitives handling null
.
This method returns null
if null
array input.
This method returns null
for a null
input array.
Boolean
array, may be null
* @param valueForNull the value to insert if null
found
* @return a boolean
array, null
if null array input
*/
- public static boolean[] toPrimitive(final Boolean[] array, final boolean valueForNull) {
+ public static boolean[] toPrimitive(Boolean[] array, boolean valueForNull) {
if (array == null) {
return null;
} else if (array.length == 0) {
@@ -2253,12 +3157,12 @@
/**
* Converts an array of primitive booleans to objects.
* - *This method returns null
if null
array input.
This method returns null
for a null
input array.
boolean
array
* @return a Boolean
array, null
if null array input
*/
- public static Boolean[] toObject(final boolean[] array) {
+ public static Boolean[] toObject(boolean[] array) {
if (array == null) {
return null;
} else if (array.length == 0) {
@@ -2271,4 +3175,1705 @@
return result;
}
+ // ----------------------------------------------------------------------
+ /**
+ * Checks if an array of Objects is empty or null
.
true
if the array is empty or null
+ * @since 2.1
+ */
+ public static boolean isEmpty(Object[] array) {
+ return array == null || array.length == 0;
+ }
+
+ /**
+ * Checks if an array of primitive longs is empty or null
.
true
if the array is empty or null
+ * @since 2.1
+ */
+ public static boolean isEmpty(long[] array) {
+ return array == null || array.length == 0;
+ }
+
+ /**
+ * Checks if an array of primitive ints is empty or null
.
true
if the array is empty or null
+ * @since 2.1
+ */
+ public static boolean isEmpty(int[] array) {
+ return array == null || array.length == 0;
+ }
+
+ /**
+ * Checks if an array of primitive shorts is empty or null
.
true
if the array is empty or null
+ * @since 2.1
+ */
+ public static boolean isEmpty(short[] array) {
+ return array == null || array.length == 0;
+ }
+
+ /**
+ * Checks if an array of primitive chars is empty or null
.
true
if the array is empty or null
+ * @since 2.1
+ */
+ public static boolean isEmpty(char[] array) {
+ return array == null || array.length == 0;
+ }
+
+ /**
+ * Checks if an array of primitive bytes is empty or null
.
true
if the array is empty or null
+ * @since 2.1
+ */
+ public static boolean isEmpty(byte[] array) {
+ return array == null || array.length == 0;
+ }
+
+ /**
+ * Checks if an array of primitive doubles is empty or null
.
true
if the array is empty or null
+ * @since 2.1
+ */
+ public static boolean isEmpty(double[] array) {
+ return array == null || array.length == 0;
+ }
+
+ /**
+ * Checks if an array of primitive floats is empty or null
.
true
if the array is empty or null
+ * @since 2.1
+ */
+ public static boolean isEmpty(float[] array) {
+ return array == null || array.length == 0;
+ }
+
+ /**
+ * Checks if an array of primitive booleans is empty or null
.
true
if the array is empty or null
+ * @since 2.1
+ */
+ public static boolean isEmpty(boolean[] array) {
+ return array == null || array.length == 0;
+ }
+
+ // ----------------------------------------------------------------------
+ /**
+ * Checks if an array of Objects is not empty or not null
.
true
if the array is not empty or not null
+ * @since 2.5
+ */
+ public static boolean isNotEmpty(Object[] array) {
+ return (array != null && array.length != 0);
+ }
+
+ /**
+ * Checks if an array of primitive longs is not empty or not null
.
true
if the array is not empty or not null
+ * @since 2.5
+ */
+ public static boolean isNotEmpty(long[] array) {
+ return (array != null && array.length != 0);
+ }
+
+ /**
+ * Checks if an array of primitive ints is not empty or not null
.
true
if the array is not empty or not null
+ * @since 2.5
+ */
+ public static boolean isNotEmpty(int[] array) {
+ return (array != null && array.length != 0);
+ }
+
+ /**
+ * Checks if an array of primitive shorts is not empty or not null
.
true
if the array is not empty or not null
+ * @since 2.5
+ */
+ public static boolean isNotEmpty(short[] array) {
+ return (array != null && array.length != 0);
+ }
+
+ /**
+ * Checks if an array of primitive chars is not empty or not null
.
true
if the array is not empty or not null
+ * @since 2.5
+ */
+ public static boolean isNotEmpty(char[] array) {
+ return (array != null && array.length != 0);
+ }
+
+ /**
+ * Checks if an array of primitive bytes is not empty or not null
.
true
if the array is not empty or not null
+ * @since 2.5
+ */
+ public static boolean isNotEmpty(byte[] array) {
+ return (array != null && array.length != 0);
+ }
+
+ /**
+ * Checks if an array of primitive doubles is not empty or not null
.
true
if the array is not empty or not null
+ * @since 2.5
+ */
+ public static boolean isNotEmpty(double[] array) {
+ return (array != null && array.length != 0);
+ }
+
+ /**
+ * Checks if an array of primitive floats is not empty or not null
.
true
if the array is not empty or not null
+ * @since 2.5
+ */
+ public static boolean isNotEmpty(float[] array) {
+ return (array != null && array.length != 0);
+ }
+
+ /**
+ * Checks if an array of primitive booleans is not empty or not null
.
true
if the array is not empty or not null
+ * @since 2.5
+ */
+ public static boolean isNotEmpty(boolean[] array) {
+ return (array != null && array.length != 0);
+ }
+
+ /**
+ * Adds all the elements of the given arrays into a new array.
+ *The new array contains all of the element of array1
followed
+ * by all of the elements array2
. When an array is returned, it is always
+ * a new array.
+ * ArrayUtils.addAll(null, null) = null + * ArrayUtils.addAll(array1, null) = cloned copy of array1 + * ArrayUtils.addAll(null, array2) = cloned copy of array2 + * ArrayUtils.addAll([], []) = [] + * ArrayUtils.addAll([null], [null]) = [null, null] + * ArrayUtils.addAll(["a", "b", "c"], ["1", "2", "3"]) = ["a", "b", "c", "1", "2", "3"] + *+ * + * @param array1 the first array whose elements are added to the new array, may be
null
+ * @param array2 the second array whose elements are added to the new array, may be null
+ * @return The new array, null
if both arrays are null
.
+ * The type of the new array is the type of the first array,
+ * unless the first array is null, in which case the type is the same as the second array.
+ * @since 2.1
+ * @throws IllegalArgumentException if the array types are incompatible
+ */
+ public static Object[] addAll(Object[] array1, Object[] array2) {
+ if (array1 == null) {
+ return clone(array2);
+ } else if (array2 == null) {
+ return clone(array1);
+ }
+ Object[] joinedArray = (Object[]) Array.newInstance(array1.getClass().getComponentType(),
+ array1.length + array2.length);
+ System.arraycopy(array1, 0, joinedArray, 0, array1.length);
+ try {
+ System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
+ } catch (ArrayStoreException ase) {
+ // Check if problem was due to incompatible types
+ /*
+ * We do this here, rather than before the copy because:
+ * - it would be a wasted check most of the time
+ * - safer, in case check turns out to be too strict
+ */
+ final Class type1 = array1.getClass().getComponentType();
+ final Class type2 = array2.getClass().getComponentType();
+ if (!type1.isAssignableFrom(type2)){
+ throw new IllegalArgumentException("Cannot store "+type2.getName()+" in an array of "+type1.getName());
+ }
+ throw ase; // No, so rethrow original
+ }
+ return joinedArray;
+ }
+
+ /**
+ * Adds all the elements of the given arrays into a new array.
+ *The new array contains all of the element of array1
followed
+ * by all of the elements array2
. When an array is returned, it is always
+ * a new array.
+ * ArrayUtils.addAll(array1, null) = cloned copy of array1 + * ArrayUtils.addAll(null, array2) = cloned copy of array2 + * ArrayUtils.addAll([], []) = [] + *+ * + * @param array1 the first array whose elements are added to the new array. + * @param array2 the second array whose elements are added to the new array. + * @return The new boolean[] array. + * @since 2.1 + */ + public static boolean[] addAll(boolean[] array1, boolean[] array2) { + if (array1 == null) { + return clone(array2); + } else if (array2 == null) { + return clone(array1); + } + boolean[] joinedArray = new boolean[array1.length + array2.length]; + System.arraycopy(array1, 0, joinedArray, 0, array1.length); + System.arraycopy(array2, 0, joinedArray, array1.length, array2.length); + return joinedArray; + } + + /** + *
Adds all the elements of the given arrays into a new array.
+ *The new array contains all of the element of array1
followed
+ * by all of the elements array2
. When an array is returned, it is always
+ * a new array.
+ * ArrayUtils.addAll(array1, null) = cloned copy of array1 + * ArrayUtils.addAll(null, array2) = cloned copy of array2 + * ArrayUtils.addAll([], []) = [] + *+ * + * @param array1 the first array whose elements are added to the new array. + * @param array2 the second array whose elements are added to the new array. + * @return The new char[] array. + * @since 2.1 + */ + public static char[] addAll(char[] array1, char[] array2) { + if (array1 == null) { + return clone(array2); + } else if (array2 == null) { + return clone(array1); + } + char[] joinedArray = new char[array1.length + array2.length]; + System.arraycopy(array1, 0, joinedArray, 0, array1.length); + System.arraycopy(array2, 0, joinedArray, array1.length, array2.length); + return joinedArray; + } + + /** + *
Adds all the elements of the given arrays into a new array.
+ *The new array contains all of the element of array1
followed
+ * by all of the elements array2
. When an array is returned, it is always
+ * a new array.
+ * ArrayUtils.addAll(array1, null) = cloned copy of array1 + * ArrayUtils.addAll(null, array2) = cloned copy of array2 + * ArrayUtils.addAll([], []) = [] + *+ * + * @param array1 the first array whose elements are added to the new array. + * @param array2 the second array whose elements are added to the new array. + * @return The new byte[] array. + * @since 2.1 + */ + public static byte[] addAll(byte[] array1, byte[] array2) { + if (array1 == null) { + return clone(array2); + } else if (array2 == null) { + return clone(array1); + } + byte[] joinedArray = new byte[array1.length + array2.length]; + System.arraycopy(array1, 0, joinedArray, 0, array1.length); + System.arraycopy(array2, 0, joinedArray, array1.length, array2.length); + return joinedArray; + } + + /** + *
Adds all the elements of the given arrays into a new array.
+ *The new array contains all of the element of array1
followed
+ * by all of the elements array2
. When an array is returned, it is always
+ * a new array.
+ * ArrayUtils.addAll(array1, null) = cloned copy of array1 + * ArrayUtils.addAll(null, array2) = cloned copy of array2 + * ArrayUtils.addAll([], []) = [] + *+ * + * @param array1 the first array whose elements are added to the new array. + * @param array2 the second array whose elements are added to the new array. + * @return The new short[] array. + * @since 2.1 + */ + public static short[] addAll(short[] array1, short[] array2) { + if (array1 == null) { + return clone(array2); + } else if (array2 == null) { + return clone(array1); + } + short[] joinedArray = new short[array1.length + array2.length]; + System.arraycopy(array1, 0, joinedArray, 0, array1.length); + System.arraycopy(array2, 0, joinedArray, array1.length, array2.length); + return joinedArray; + } + + /** + *
Adds all the elements of the given arrays into a new array.
+ *The new array contains all of the element of array1
followed
+ * by all of the elements array2
. When an array is returned, it is always
+ * a new array.
+ * ArrayUtils.addAll(array1, null) = cloned copy of array1 + * ArrayUtils.addAll(null, array2) = cloned copy of array2 + * ArrayUtils.addAll([], []) = [] + *+ * + * @param array1 the first array whose elements are added to the new array. + * @param array2 the second array whose elements are added to the new array. + * @return The new int[] array. + * @since 2.1 + */ + public static int[] addAll(int[] array1, int[] array2) { + if (array1 == null) { + return clone(array2); + } else if (array2 == null) { + return clone(array1); + } + int[] joinedArray = new int[array1.length + array2.length]; + System.arraycopy(array1, 0, joinedArray, 0, array1.length); + System.arraycopy(array2, 0, joinedArray, array1.length, array2.length); + return joinedArray; + } + + /** + *
Adds all the elements of the given arrays into a new array.
+ *The new array contains all of the element of array1
followed
+ * by all of the elements array2
. When an array is returned, it is always
+ * a new array.
+ * ArrayUtils.addAll(array1, null) = cloned copy of array1 + * ArrayUtils.addAll(null, array2) = cloned copy of array2 + * ArrayUtils.addAll([], []) = [] + *+ * + * @param array1 the first array whose elements are added to the new array. + * @param array2 the second array whose elements are added to the new array. + * @return The new long[] array. + * @since 2.1 + */ + public static long[] addAll(long[] array1, long[] array2) { + if (array1 == null) { + return clone(array2); + } else if (array2 == null) { + return clone(array1); + } + long[] joinedArray = new long[array1.length + array2.length]; + System.arraycopy(array1, 0, joinedArray, 0, array1.length); + System.arraycopy(array2, 0, joinedArray, array1.length, array2.length); + return joinedArray; + } + + /** + *
Adds all the elements of the given arrays into a new array.
+ *The new array contains all of the element of array1
followed
+ * by all of the elements array2
. When an array is returned, it is always
+ * a new array.
+ * ArrayUtils.addAll(array1, null) = cloned copy of array1 + * ArrayUtils.addAll(null, array2) = cloned copy of array2 + * ArrayUtils.addAll([], []) = [] + *+ * + * @param array1 the first array whose elements are added to the new array. + * @param array2 the second array whose elements are added to the new array. + * @return The new float[] array. + * @since 2.1 + */ + public static float[] addAll(float[] array1, float[] array2) { + if (array1 == null) { + return clone(array2); + } else if (array2 == null) { + return clone(array1); + } + float[] joinedArray = new float[array1.length + array2.length]; + System.arraycopy(array1, 0, joinedArray, 0, array1.length); + System.arraycopy(array2, 0, joinedArray, array1.length, array2.length); + return joinedArray; + } + + /** + *
Adds all the elements of the given arrays into a new array.
+ *The new array contains all of the element of array1
followed
+ * by all of the elements array2
. When an array is returned, it is always
+ * a new array.
+ * ArrayUtils.addAll(array1, null) = cloned copy of array1 + * ArrayUtils.addAll(null, array2) = cloned copy of array2 + * ArrayUtils.addAll([], []) = [] + *+ * + * @param array1 the first array whose elements are added to the new array. + * @param array2 the second array whose elements are added to the new array. + * @return The new double[] array. + * @since 2.1 + */ + public static double[] addAll(double[] array1, double[] array2) { + if (array1 == null) { + return clone(array2); + } else if (array2 == null) { + return clone(array1); + } + double[] joinedArray = new double[array1.length + array2.length]; + System.arraycopy(array1, 0, joinedArray, 0, array1.length); + System.arraycopy(array2, 0, joinedArray, array1.length, array2.length); + return joinedArray; + } + + /** + *
Copies the given array and adds the given element at the end of the new array.
+ * + *The new array contains the same elements of the input + * array plus the given element in the last position. The component type of + * the new array is the same as that of the input array.
+ * + *If the input array is null
, a new one element array is returned
+ * whose component type is the same as the element, unless the element itself is null,
+ * in which case the return type is Object[]
+ * ArrayUtils.add(null, null) = [null] + * ArrayUtils.add(null, "a") = ["a"] + * ArrayUtils.add(["a"], null) = ["a", null] + * ArrayUtils.add(["a"], "b") = ["a", "b"] + * ArrayUtils.add(["a", "b"], "c") = ["a", "b", "c"] + *+ * + * @param array the array to "add" the element to, may be
null
+ * @param element the object to add, may be null
+ * @return A new array containing the existing elements plus the new element
+ * The returned array type will be that of the input array (unless null),
+ * in which case it will have the same type as the element.
+ * @since 2.1
+ */
+ public static Object[] add(Object[] array, Object element) {
+ Class type;
+ if (array != null){
+ type = array.getClass();
+ } else if (element != null) {
+ type = element.getClass();
+ } else {
+ type = Object.class;
+ }
+ Object[] newArray = (Object[]) copyArrayGrow1(array, type);
+ newArray[newArray.length - 1] = element;
+ return newArray;
+ }
+
+ /**
+ * Copies the given array and adds the given element at the end of the new array.
+ * + *The new array contains the same elements of the input + * array plus the given element in the last position. The component type of + * the new array is the same as that of the input array.
+ * + *If the input array is null
, a new one element array is returned
+ * whose component type is the same as the element.
+ * ArrayUtils.add(null, true) = [true] + * ArrayUtils.add([true], false) = [true, false] + * ArrayUtils.add([true, false], true) = [true, false, true] + *+ * + * @param array the array to copy and add the element to, may be
null
+ * @param element the object to add at the last index of the new array
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static boolean[] add(boolean[] array, boolean element) {
+ boolean[] newArray = (boolean[])copyArrayGrow1(array, Boolean.TYPE);
+ newArray[newArray.length - 1] = element;
+ return newArray;
+ }
+
+ /**
+ * Copies the given array and adds the given element at the end of the new array.
+ * + *The new array contains the same elements of the input + * array plus the given element in the last position. The component type of + * the new array is the same as that of the input array.
+ * + *If the input array is null
, a new one element array is returned
+ * whose component type is the same as the element.
+ * ArrayUtils.add(null, 0) = [0] + * ArrayUtils.add([1], 0) = [1, 0] + * ArrayUtils.add([1, 0], 1) = [1, 0, 1] + *+ * + * @param array the array to copy and add the element to, may be
null
+ * @param element the object to add at the last index of the new array
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static byte[] add(byte[] array, byte element) {
+ byte[] newArray = (byte[])copyArrayGrow1(array, Byte.TYPE);
+ newArray[newArray.length - 1] = element;
+ return newArray;
+ }
+
+ /**
+ * Copies the given array and adds the given element at the end of the new array.
+ * + *The new array contains the same elements of the input + * array plus the given element in the last position. The component type of + * the new array is the same as that of the input array.
+ * + *If the input array is null
, a new one element array is returned
+ * whose component type is the same as the element.
+ * ArrayUtils.add(null, '0') = ['0'] + * ArrayUtils.add(['1'], '0') = ['1', '0'] + * ArrayUtils.add(['1', '0'], '1') = ['1', '0', '1'] + *+ * + * @param array the array to copy and add the element to, may be
null
+ * @param element the object to add at the last index of the new array
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static char[] add(char[] array, char element) {
+ char[] newArray = (char[])copyArrayGrow1(array, Character.TYPE);
+ newArray[newArray.length - 1] = element;
+ return newArray;
+ }
+
+ /**
+ * Copies the given array and adds the given element at the end of the new array.
+ * + *The new array contains the same elements of the input + * array plus the given element in the last position. The component type of + * the new array is the same as that of the input array.
+ * + *If the input array is null
, a new one element array is returned
+ * whose component type is the same as the element.
+ * ArrayUtils.add(null, 0) = [0] + * ArrayUtils.add([1], 0) = [1, 0] + * ArrayUtils.add([1, 0], 1) = [1, 0, 1] + *+ * + * @param array the array to copy and add the element to, may be
null
+ * @param element the object to add at the last index of the new array
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static double[] add(double[] array, double element) {
+ double[] newArray = (double[])copyArrayGrow1(array, Double.TYPE);
+ newArray[newArray.length - 1] = element;
+ return newArray;
+ }
+
+ /**
+ * Copies the given array and adds the given element at the end of the new array.
+ * + *The new array contains the same elements of the input + * array plus the given element in the last position. The component type of + * the new array is the same as that of the input array.
+ * + *If the input array is null
, a new one element array is returned
+ * whose component type is the same as the element.
+ * ArrayUtils.add(null, 0) = [0] + * ArrayUtils.add([1], 0) = [1, 0] + * ArrayUtils.add([1, 0], 1) = [1, 0, 1] + *+ * + * @param array the array to copy and add the element to, may be
null
+ * @param element the object to add at the last index of the new array
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static float[] add(float[] array, float element) {
+ float[] newArray = (float[])copyArrayGrow1(array, Float.TYPE);
+ newArray[newArray.length - 1] = element;
+ return newArray;
+ }
+
+ /**
+ * Copies the given array and adds the given element at the end of the new array.
+ * + *The new array contains the same elements of the input + * array plus the given element in the last position. The component type of + * the new array is the same as that of the input array.
+ * + *If the input array is null
, a new one element array is returned
+ * whose component type is the same as the element.
+ * ArrayUtils.add(null, 0) = [0] + * ArrayUtils.add([1], 0) = [1, 0] + * ArrayUtils.add([1, 0], 1) = [1, 0, 1] + *+ * + * @param array the array to copy and add the element to, may be
null
+ * @param element the object to add at the last index of the new array
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static int[] add(int[] array, int element) {
+ int[] newArray = (int[])copyArrayGrow1(array, Integer.TYPE);
+ newArray[newArray.length - 1] = element;
+ return newArray;
+ }
+
+ /**
+ * Copies the given array and adds the given element at the end of the new array.
+ * + *The new array contains the same elements of the input + * array plus the given element in the last position. The component type of + * the new array is the same as that of the input array.
+ * + *If the input array is null
, a new one element array is returned
+ * whose component type is the same as the element.
+ * ArrayUtils.add(null, 0) = [0] + * ArrayUtils.add([1], 0) = [1, 0] + * ArrayUtils.add([1, 0], 1) = [1, 0, 1] + *+ * + * @param array the array to copy and add the element to, may be
null
+ * @param element the object to add at the last index of the new array
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static long[] add(long[] array, long element) {
+ long[] newArray = (long[])copyArrayGrow1(array, Long.TYPE);
+ newArray[newArray.length - 1] = element;
+ return newArray;
+ }
+
+ /**
+ * Copies the given array and adds the given element at the end of the new array.
+ * + *The new array contains the same elements of the input + * array plus the given element in the last position. The component type of + * the new array is the same as that of the input array.
+ * + *If the input array is null
, a new one element array is returned
+ * whose component type is the same as the element.
+ * ArrayUtils.add(null, 0) = [0] + * ArrayUtils.add([1], 0) = [1, 0] + * ArrayUtils.add([1, 0], 1) = [1, 0, 1] + *+ * + * @param array the array to copy and add the element to, may be
null
+ * @param element the object to add at the last index of the new array
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static short[] add(short[] array, short element) {
+ short[] newArray = (short[])copyArrayGrow1(array, Short.TYPE);
+ newArray[newArray.length - 1] = element;
+ return newArray;
+ }
+
+ /**
+ * Returns a copy of the given array of size 1 greater than the argument.
+ * The last value of the array is left to the default value.
+ *
+ * @param array The array to copy, must not be null
.
+ * @param newArrayComponentType If array
is null
, create a
+ * size 1 array of this type.
+ * @return A new copy of the array of size 1 greater than the input.
+ */
+ private static Object copyArrayGrow1(Object array, Class newArrayComponentType) {
+ if (array != null) {
+ int arrayLength = Array.getLength(array);
+ Object newArray = Array.newInstance(array.getClass().getComponentType(), arrayLength + 1);
+ System.arraycopy(array, 0, newArray, 0, arrayLength);
+ return newArray;
+ }
+ return Array.newInstance(newArrayComponentType, 1);
+ }
+
+ /**
+ * Inserts the specified element at the specified position in the array. + * Shifts the element currently at that position (if any) and any subsequent + * elements to the right (adds one to their indices).
+ * + *This method returns a new array with the same elements of the input + * array plus the given element on the specified position. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *If the input array is null
, a new one element array is returned
+ * whose component type is the same as the element.
+ * ArrayUtils.add(null, 0, null) = [null] + * ArrayUtils.add(null, 0, "a") = ["a"] + * ArrayUtils.add(["a"], 1, null) = ["a", null] + * ArrayUtils.add(["a"], 1, "b") = ["a", "b"] + * ArrayUtils.add(["a", "b"], 3, "c") = ["a", "b", "c"] + *+ * + * @param array the array to add the element to, may be
null
+ * @param index the position of the new object
+ * @param element the object to add
+ * @return A new array containing the existing elements and the new element
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index > array.length).
+ */
+ public static Object[] add(Object[] array, int index, Object element) {
+ Class clss = null;
+ if (array != null) {
+ clss = array.getClass().getComponentType();
+ } else if (element != null) {
+ clss = element.getClass();
+ } else {
+ return new Object[]{null};
+ }
+ return (Object[]) add(array, index, element, clss);
+ }
+
+ /**
+ * Inserts the specified element at the specified position in the array. + * Shifts the element currently at that position (if any) and any subsequent + * elements to the right (adds one to their indices).
+ * + *This method returns a new array with the same elements of the input + * array plus the given element on the specified position. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *If the input array is null
, a new one element array is returned
+ * whose component type is the same as the element.
+ * ArrayUtils.add(null, 0, true) = [true] + * ArrayUtils.add([true], 0, false) = [false, true] + * ArrayUtils.add([false], 1, true) = [false, true] + * ArrayUtils.add([true, false], 1, true) = [true, true, false] + *+ * + * @param array the array to add the element to, may be
null
+ * @param index the position of the new object
+ * @param element the object to add
+ * @return A new array containing the existing elements and the new element
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index > array.length).
+ */
+ public static boolean[] add(boolean[] array, int index, boolean element) {
+ return (boolean[]) add(array, index, BooleanUtils.toBooleanObject(element), Boolean.TYPE);
+ }
+
+ /**
+ * Inserts the specified element at the specified position in the array. + * Shifts the element currently at that position (if any) and any subsequent + * elements to the right (adds one to their indices).
+ * + *This method returns a new array with the same elements of the input + * array plus the given element on the specified position. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *If the input array is null
, a new one element array is returned
+ * whose component type is the same as the element.
+ * ArrayUtils.add(null, 0, 'a') = ['a'] + * ArrayUtils.add(['a'], 0, 'b') = ['b', 'a'] + * ArrayUtils.add(['a', 'b'], 0, 'c') = ['c', 'a', 'b'] + * ArrayUtils.add(['a', 'b'], 1, 'k') = ['a', 'k', 'b'] + * ArrayUtils.add(['a', 'b', 'c'], 1, 't') = ['a', 't', 'b', 'c'] + *+ * + * @param array the array to add the element to, may be
null
+ * @param index the position of the new object
+ * @param element the object to add
+ * @return A new array containing the existing elements and the new element
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index > array.length).
+ */
+ public static char[] add(char[] array, int index, char element) {
+ return (char[]) add(array, index, new Character(element), Character.TYPE);
+ }
+
+ /**
+ * Inserts the specified element at the specified position in the array. + * Shifts the element currently at that position (if any) and any subsequent + * elements to the right (adds one to their indices).
+ * + *This method returns a new array with the same elements of the input + * array plus the given element on the specified position. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *If the input array is null
, a new one element array is returned
+ * whose component type is the same as the element.
+ * ArrayUtils.add([1], 0, 2) = [2, 1] + * ArrayUtils.add([2, 6], 2, 3) = [2, 6, 3] + * ArrayUtils.add([2, 6], 0, 1) = [1, 2, 6] + * ArrayUtils.add([2, 6, 3], 2, 1) = [2, 6, 1, 3] + *+ * + * @param array the array to add the element to, may be
null
+ * @param index the position of the new object
+ * @param element the object to add
+ * @return A new array containing the existing elements and the new element
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index > array.length).
+ */
+ public static byte[] add(byte[] array, int index, byte element) {
+ return (byte[]) add(array, index, new Byte(element), Byte.TYPE);
+ }
+
+ /**
+ * Inserts the specified element at the specified position in the array. + * Shifts the element currently at that position (if any) and any subsequent + * elements to the right (adds one to their indices).
+ * + *This method returns a new array with the same elements of the input + * array plus the given element on the specified position. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *If the input array is null
, a new one element array is returned
+ * whose component type is the same as the element.
+ * ArrayUtils.add([1], 0, 2) = [2, 1] + * ArrayUtils.add([2, 6], 2, 10) = [2, 6, 10] + * ArrayUtils.add([2, 6], 0, -4) = [-4, 2, 6] + * ArrayUtils.add([2, 6, 3], 2, 1) = [2, 6, 1, 3] + *+ * + * @param array the array to add the element to, may be
null
+ * @param index the position of the new object
+ * @param element the object to add
+ * @return A new array containing the existing elements and the new element
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index > array.length).
+ */
+ public static short[] add(short[] array, int index, short element) {
+ return (short[]) add(array, index, new Short(element), Short.TYPE);
+ }
+
+ /**
+ * Inserts the specified element at the specified position in the array. + * Shifts the element currently at that position (if any) and any subsequent + * elements to the right (adds one to their indices).
+ * + *This method returns a new array with the same elements of the input + * array plus the given element on the specified position. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *If the input array is null
, a new one element array is returned
+ * whose component type is the same as the element.
+ * ArrayUtils.add([1], 0, 2) = [2, 1] + * ArrayUtils.add([2, 6], 2, 10) = [2, 6, 10] + * ArrayUtils.add([2, 6], 0, -4) = [-4, 2, 6] + * ArrayUtils.add([2, 6, 3], 2, 1) = [2, 6, 1, 3] + *+ * + * @param array the array to add the element to, may be
null
+ * @param index the position of the new object
+ * @param element the object to add
+ * @return A new array containing the existing elements and the new element
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index > array.length).
+ */
+ public static int[] add(int[] array, int index, int element) {
+ return (int[]) add(array, index, new Integer(element), Integer.TYPE);
+ }
+
+ /**
+ * Inserts the specified element at the specified position in the array. + * Shifts the element currently at that position (if any) and any subsequent + * elements to the right (adds one to their indices).
+ * + *This method returns a new array with the same elements of the input + * array plus the given element on the specified position. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *If the input array is null
, a new one element array is returned
+ * whose component type is the same as the element.
+ * ArrayUtils.add([1L], 0, 2L) = [2L, 1L] + * ArrayUtils.add([2L, 6L], 2, 10L) = [2L, 6L, 10L] + * ArrayUtils.add([2L, 6L], 0, -4L) = [-4L, 2L, 6L] + * ArrayUtils.add([2L, 6L, 3L], 2, 1L) = [2L, 6L, 1L, 3L] + *+ * + * @param array the array to add the element to, may be
null
+ * @param index the position of the new object
+ * @param element the object to add
+ * @return A new array containing the existing elements and the new element
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index > array.length).
+ */
+ public static long[] add(long[] array, int index, long element) {
+ return (long[]) add(array, index, new Long(element), Long.TYPE);
+ }
+
+ /**
+ * Inserts the specified element at the specified position in the array. + * Shifts the element currently at that position (if any) and any subsequent + * elements to the right (adds one to their indices).
+ * + *This method returns a new array with the same elements of the input + * array plus the given element on the specified position. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *If the input array is null
, a new one element array is returned
+ * whose component type is the same as the element.
+ * ArrayUtils.add([1.1f], 0, 2.2f) = [2.2f, 1.1f] + * ArrayUtils.add([2.3f, 6.4f], 2, 10.5f) = [2.3f, 6.4f, 10.5f] + * ArrayUtils.add([2.6f, 6.7f], 0, -4.8f) = [-4.8f, 2.6f, 6.7f] + * ArrayUtils.add([2.9f, 6.0f, 0.3f], 2, 1.0f) = [2.9f, 6.0f, 1.0f, 0.3f] + *+ * + * @param array the array to add the element to, may be
null
+ * @param index the position of the new object
+ * @param element the object to add
+ * @return A new array containing the existing elements and the new element
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index > array.length).
+ */
+ public static float[] add(float[] array, int index, float element) {
+ return (float[]) add(array, index, new Float(element), Float.TYPE);
+ }
+
+ /**
+ * Inserts the specified element at the specified position in the array. + * Shifts the element currently at that position (if any) and any subsequent + * elements to the right (adds one to their indices).
+ * + *This method returns a new array with the same elements of the input + * array plus the given element on the specified position. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *If the input array is null
, a new one element array is returned
+ * whose component type is the same as the element.
+ * ArrayUtils.add([1.1], 0, 2.2) = [2.2, 1.1] + * ArrayUtils.add([2.3, 6.4], 2, 10.5) = [2.3, 6.4, 10.5] + * ArrayUtils.add([2.6, 6.7], 0, -4.8) = [-4.8, 2.6, 6.7] + * ArrayUtils.add([2.9, 6.0, 0.3], 2, 1.0) = [2.9, 6.0, 1.0, 0.3] + *+ * + * @param array the array to add the element to, may be
null
+ * @param index the position of the new object
+ * @param element the object to add
+ * @return A new array containing the existing elements and the new element
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index > array.length).
+ */
+ public static double[] add(double[] array, int index, double element) {
+ return (double[]) add(array, index, new Double(element), Double.TYPE);
+ }
+
+ /**
+ * Underlying implementation of add(array, index, element) methods.
+ * The last parameter is the class, which may not equal element.getClass
+ * for primitives.
+ *
+ * @param array the array to add the element to, may be null
+ * @param index the position of the new object
+ * @param element the object to add
+ * @param clss the type of the element being added
+ * @return A new array containing the existing elements and the new element
+ */
+ private static Object add(Object array, int index, Object element, Class clss) {
+ if (array == null) {
+ if (index != 0) {
+ throw new IndexOutOfBoundsException("Index: " + index + ", Length: 0");
+ }
+ Object joinedArray = Array.newInstance(clss, 1);
+ Array.set(joinedArray, 0, element);
+ return joinedArray;
+ }
+ int length = Array.getLength(array);
+ if (index > length || index < 0) {
+ throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
+ }
+ Object result = Array.newInstance(clss, length + 1);
+ System.arraycopy(array, 0, result, 0, index);
+ Array.set(result, index, element);
+ if (index < length) {
+ System.arraycopy(array, index, result, index + 1, length - index);
+ }
+ return result;
+ }
+
+ /**
+ * Removes the element at the specified position from the specified array. + * All subsequent elements are shifted to the left (substracts one from + * their indices).
+ * + *This method returns a new array with the same elements of the input + * array except the element on the specified position. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *If the input array is null
, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ * ArrayUtils.remove(["a"], 0) = [] + * ArrayUtils.remove(["a", "b"], 0) = ["b"] + * ArrayUtils.remove(["a", "b"], 1) = ["a"] + * ArrayUtils.remove(["a", "b", "c"], 1) = ["a", "c"] + *+ * + * @param array the array to remove the element from, may not be
null
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is null
.
+ * @since 2.1
+ */
+ public static Object[] remove(Object[] array, int index) {
+ return (Object[]) remove((Object) array, index);
+ }
+
+ /**
+ * Removes the first occurrence of the specified element from the + * specified array. All subsequent elements are shifted to the left + * (substracts one from their indices). If the array doesn't contains + * such an element, no elements are removed from the array.
+ * + *This method returns a new array with the same elements of the input + * array except the first occurrence of the specified element. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *+ * ArrayUtils.removeElement(null, "a") = null + * ArrayUtils.removeElement([], "a") = [] + * ArrayUtils.removeElement(["a"], "b") = ["a"] + * ArrayUtils.removeElement(["a", "b"], "a") = ["b"] + * ArrayUtils.removeElement(["a", "b", "a"], "a") = ["b", "a"] + *+ * + * @param array the array to remove the element from, may be
null
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static Object[] removeElement(Object[] array, Object element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * Removes the element at the specified position from the specified array. + * All subsequent elements are shifted to the left (substracts one from + * their indices).
+ * + *This method returns a new array with the same elements of the input + * array except the element on the specified position. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *If the input array is null
, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ * ArrayUtils.remove([true], 0) = [] + * ArrayUtils.remove([true, false], 0) = [false] + * ArrayUtils.remove([true, false], 1) = [true] + * ArrayUtils.remove([true, true, false], 1) = [true, false] + *+ * + * @param array the array to remove the element from, may not be
null
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is null
.
+ * @since 2.1
+ */
+ public static boolean[] remove(boolean[] array, int index) {
+ return (boolean[]) remove((Object) array, index);
+ }
+
+ /**
+ * Removes the first occurrence of the specified element from the + * specified array. All subsequent elements are shifted to the left + * (substracts one from their indices). If the array doesn't contains + * such an element, no elements are removed from the array.
+ * + *This method returns a new array with the same elements of the input + * array except the first occurrence of the specified element. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *+ * ArrayUtils.removeElement(null, true) = null + * ArrayUtils.removeElement([], true) = [] + * ArrayUtils.removeElement([true], false) = [true] + * ArrayUtils.removeElement([true, false], false) = [true] + * ArrayUtils.removeElement([true, false, true], true) = [false, true] + *+ * + * @param array the array to remove the element from, may be
null
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static boolean[] removeElement(boolean[] array, boolean element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * Removes the element at the specified position from the specified array. + * All subsequent elements are shifted to the left (substracts one from + * their indices).
+ * + *This method returns a new array with the same elements of the input + * array except the element on the specified position. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *If the input array is null
, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ * ArrayUtils.remove([1], 0) = [] + * ArrayUtils.remove([1, 0], 0) = [0] + * ArrayUtils.remove([1, 0], 1) = [1] + * ArrayUtils.remove([1, 0, 1], 1) = [1, 1] + *+ * + * @param array the array to remove the element from, may not be
null
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is null
.
+ * @since 2.1
+ */
+ public static byte[] remove(byte[] array, int index) {
+ return (byte[]) remove((Object) array, index);
+ }
+
+ /**
+ * Removes the first occurrence of the specified element from the + * specified array. All subsequent elements are shifted to the left + * (substracts one from their indices). If the array doesn't contains + * such an element, no elements are removed from the array.
+ * + *This method returns a new array with the same elements of the input + * array except the first occurrence of the specified element. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *+ * ArrayUtils.removeElement(null, 1) = null + * ArrayUtils.removeElement([], 1) = [] + * ArrayUtils.removeElement([1], 0) = [1] + * ArrayUtils.removeElement([1, 0], 0) = [1] + * ArrayUtils.removeElement([1, 0, 1], 1) = [0, 1] + *+ * + * @param array the array to remove the element from, may be
null
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static byte[] removeElement(byte[] array, byte element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * Removes the element at the specified position from the specified array. + * All subsequent elements are shifted to the left (substracts one from + * their indices).
+ * + *This method returns a new array with the same elements of the input + * array except the element on the specified position. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *If the input array is null
, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ * ArrayUtils.remove(['a'], 0) = [] + * ArrayUtils.remove(['a', 'b'], 0) = ['b'] + * ArrayUtils.remove(['a', 'b'], 1) = ['a'] + * ArrayUtils.remove(['a', 'b', 'c'], 1) = ['a', 'c'] + *+ * + * @param array the array to remove the element from, may not be
null
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is null
.
+ * @since 2.1
+ */
+ public static char[] remove(char[] array, int index) {
+ return (char[]) remove((Object) array, index);
+ }
+
+ /**
+ * Removes the first occurrence of the specified element from the + * specified array. All subsequent elements are shifted to the left + * (substracts one from their indices). If the array doesn't contains + * such an element, no elements are removed from the array.
+ * + *This method returns a new array with the same elements of the input + * array except the first occurrence of the specified element. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *+ * ArrayUtils.removeElement(null, 'a') = null + * ArrayUtils.removeElement([], 'a') = [] + * ArrayUtils.removeElement(['a'], 'b') = ['a'] + * ArrayUtils.removeElement(['a', 'b'], 'a') = ['b'] + * ArrayUtils.removeElement(['a', 'b', 'a'], 'a') = ['b', 'a'] + *+ * + * @param array the array to remove the element from, may be
null
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static char[] removeElement(char[] array, char element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * Removes the element at the specified position from the specified array. + * All subsequent elements are shifted to the left (substracts one from + * their indices).
+ * + *This method returns a new array with the same elements of the input + * array except the element on the specified position. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *If the input array is null
, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ * ArrayUtils.remove([1.1], 0) = [] + * ArrayUtils.remove([2.5, 6.0], 0) = [6.0] + * ArrayUtils.remove([2.5, 6.0], 1) = [2.5] + * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8] + *+ * + * @param array the array to remove the element from, may not be
null
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is null
.
+ * @since 2.1
+ */
+ public static double[] remove(double[] array, int index) {
+ return (double[]) remove((Object) array, index);
+ }
+
+ /**
+ * Removes the first occurrence of the specified element from the + * specified array. All subsequent elements are shifted to the left + * (substracts one from their indices). If the array doesn't contains + * such an element, no elements are removed from the array.
+ * + *This method returns a new array with the same elements of the input + * array except the first occurrence of the specified element. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *+ * ArrayUtils.removeElement(null, 1.1) = null + * ArrayUtils.removeElement([], 1.1) = [] + * ArrayUtils.removeElement([1.1], 1.2) = [1.1] + * ArrayUtils.removeElement([1.1, 2.3], 1.1) = [2.3] + * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1] + *+ * + * @param array the array to remove the element from, may be
null
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static double[] removeElement(double[] array, double element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * Removes the element at the specified position from the specified array. + * All subsequent elements are shifted to the left (substracts one from + * their indices).
+ * + *This method returns a new array with the same elements of the input + * array except the element on the specified position. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *If the input array is null
, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ * ArrayUtils.remove([1.1], 0) = [] + * ArrayUtils.remove([2.5, 6.0], 0) = [6.0] + * ArrayUtils.remove([2.5, 6.0], 1) = [2.5] + * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8] + *+ * + * @param array the array to remove the element from, may not be
null
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is null
.
+ * @since 2.1
+ */
+ public static float[] remove(float[] array, int index) {
+ return (float[]) remove((Object) array, index);
+ }
+
+ /**
+ * Removes the first occurrence of the specified element from the + * specified array. All subsequent elements are shifted to the left + * (substracts one from their indices). If the array doesn't contains + * such an element, no elements are removed from the array.
+ * + *This method returns a new array with the same elements of the input + * array except the first occurrence of the specified element. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *+ * ArrayUtils.removeElement(null, 1.1) = null + * ArrayUtils.removeElement([], 1.1) = [] + * ArrayUtils.removeElement([1.1], 1.2) = [1.1] + * ArrayUtils.removeElement([1.1, 2.3], 1.1) = [2.3] + * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1] + *+ * + * @param array the array to remove the element from, may be
null
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static float[] removeElement(float[] array, float element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * Removes the element at the specified position from the specified array. + * All subsequent elements are shifted to the left (substracts one from + * their indices).
+ * + *This method returns a new array with the same elements of the input + * array except the element on the specified position. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *If the input array is null
, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ * ArrayUtils.remove([1], 0) = [] + * ArrayUtils.remove([2, 6], 0) = [6] + * ArrayUtils.remove([2, 6], 1) = [2] + * ArrayUtils.remove([2, 6, 3], 1) = [2, 3] + *+ * + * @param array the array to remove the element from, may not be
null
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is null
.
+ * @since 2.1
+ */
+ public static int[] remove(int[] array, int index) {
+ return (int[]) remove((Object) array, index);
+ }
+
+ /**
+ * Removes the first occurrence of the specified element from the + * specified array. All subsequent elements are shifted to the left + * (substracts one from their indices). If the array doesn't contains + * such an element, no elements are removed from the array.
+ * + *This method returns a new array with the same elements of the input + * array except the first occurrence of the specified element. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *+ * ArrayUtils.removeElement(null, 1) = null + * ArrayUtils.removeElement([], 1) = [] + * ArrayUtils.removeElement([1], 2) = [1] + * ArrayUtils.removeElement([1, 3], 1) = [3] + * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1] + *+ * + * @param array the array to remove the element from, may be
null
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static int[] removeElement(int[] array, int element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * Removes the element at the specified position from the specified array. + * All subsequent elements are shifted to the left (substracts one from + * their indices).
+ * + *This method returns a new array with the same elements of the input + * array except the element on the specified position. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *If the input array is null
, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ * ArrayUtils.remove([1], 0) = [] + * ArrayUtils.remove([2, 6], 0) = [6] + * ArrayUtils.remove([2, 6], 1) = [2] + * ArrayUtils.remove([2, 6, 3], 1) = [2, 3] + *+ * + * @param array the array to remove the element from, may not be
null
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is null
.
+ * @since 2.1
+ */
+ public static long[] remove(long[] array, int index) {
+ return (long[]) remove((Object) array, index);
+ }
+
+ /**
+ * Removes the first occurrence of the specified element from the + * specified array. All subsequent elements are shifted to the left + * (substracts one from their indices). If the array doesn't contains + * such an element, no elements are removed from the array.
+ * + *This method returns a new array with the same elements of the input + * array except the first occurrence of the specified element. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *+ * ArrayUtils.removeElement(null, 1) = null + * ArrayUtils.removeElement([], 1) = [] + * ArrayUtils.removeElement([1], 2) = [1] + * ArrayUtils.removeElement([1, 3], 1) = [3] + * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1] + *+ * + * @param array the array to remove the element from, may be
null
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static long[] removeElement(long[] array, long element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * Removes the element at the specified position from the specified array. + * All subsequent elements are shifted to the left (substracts one from + * their indices).
+ * + *This method returns a new array with the same elements of the input + * array except the element on the specified position. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *If the input array is null
, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ * ArrayUtils.remove([1], 0) = [] + * ArrayUtils.remove([2, 6], 0) = [6] + * ArrayUtils.remove([2, 6], 1) = [2] + * ArrayUtils.remove([2, 6, 3], 1) = [2, 3] + *+ * + * @param array the array to remove the element from, may not be
null
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is null
.
+ * @since 2.1
+ */
+ public static short[] remove(short[] array, int index) {
+ return (short[]) remove((Object) array, index);
+ }
+
+ /**
+ * Removes the first occurrence of the specified element from the + * specified array. All subsequent elements are shifted to the left + * (substracts one from their indices). If the array doesn't contains + * such an element, no elements are removed from the array.
+ * + *This method returns a new array with the same elements of the input + * array except the first occurrence of the specified element. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *+ * ArrayUtils.removeElement(null, 1) = null + * ArrayUtils.removeElement([], 1) = [] + * ArrayUtils.removeElement([1], 2) = [1] + * ArrayUtils.removeElement([1, 3], 1) = [3] + * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1] + *+ * + * @param array the array to remove the element from, may be
null
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static short[] removeElement(short[] array, short element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * Removes the element at the specified position from the specified array. + * All subsequent elements are shifted to the left (substracts one from + * their indices).
+ * + *This method returns a new array with the same elements of the input + * array except the element on the specified position. The component + * type of the returned array is always the same as that of the input + * array.
+ * + *If the input array is null
, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
null
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is null
.
+ * @since 2.1
+ */
+ private static Object remove(Object array, int index) {
+ int length = getLength(array);
+ if (index < 0 || index >= length) {
+ throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
+ }
+
+ Object result = Array.newInstance(array.getClass().getComponentType(), length - 1);
+ System.arraycopy(array, 0, result, 0, index);
+ if (index < length - 1) {
+ System.arraycopy(array, index + 1, result, index, length - index - 1);
+ }
+
+ return result;
+ }
+
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/BitField.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/BitField.java (.../BitField.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/BitField.java (.../BitField.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,66 +1,29 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * Operations on bit-mapped fields.
* + * @author Apache Software Foundation * @author Apache Jakarta POI * @author Scott Sanders (sanders at apache dot org) * @author Marc Johnson (mjohnson at apache dot org) * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Stephen Colebourne * @author Pete Gieser * @author Gary Gregory * @since 2.0 @@ -78,7 +41,7 @@ * BitField. Bits that are set in this mask are the bits * that this BitField operates on */ - public BitField(final int mask) { + public BitField(int mask) { _mask = mask; int count = 0; int bit_pattern = mask; @@ -101,12 +64,12 @@ * value is stored as a BitField (and so shifted left so many * bits). * - * @see #setValue + * @see #setValue(int,int) * @param holder the int data containing the bits we're interested * in * @return the selected bits, shifted right appropriately */ - public int getValue(final int holder) { + public int getValue(int holder) { return getRawValue(holder) >> _shift_count; } @@ -119,12 +82,12 @@ * value is stored as a BitField (and so shifted left so many * bits). * - * @see #setShortValue + * @see #setShortValue(short,short) * @param holder the short data containing the bits we're * interested in * @return the selected bits, shifted right appropriately */ - public short getShortValue(final short holder) { + public short getShortValue(short holder) { return (short) getValue(holder); } @@ -135,8 +98,8 @@ * interested in * @return the selected bits */ - public int getRawValue(final int holder) { - return (holder & _mask); + public int getRawValue(int holder) { + return holder & _mask; } /** @@ -146,7 +109,7 @@ * interested in * @return the selected bits */ - public short getShortRawValue(final short holder) { + public short getShortRawValue(short holder) { return (short) getRawValue(holder); } @@ -163,7 +126,7 @@ * @returntrue
if any of the bits are set,
* else false
*/
- public boolean isSet(final int holder) {
+ public boolean isSet(int holder) {
return (holder & _mask) != 0;
}
@@ -179,35 +142,35 @@
* @return true
if all of the bits are set,
* else false
*/
- public boolean isAllSet(final int holder) {
+ public boolean isAllSet(int holder) {
return (holder & _mask) == _mask;
}
/**
* Replaces the bits with new values.
* - * @see #getValue - * @param holder the int data containint the bits we're + * @see #getValue(int) + * @param holder the int data containing the bits we're * interested in * @param value the new value for the specified bits * @return the value of holder with the bits from the value * parameter replacing the old bits */ - public int setValue(final int holder, final int value) { + public int setValue(int holder, int value) { return (holder & ~_mask) | ((value << _shift_count) & _mask); } /** *Replaces the bits with new values.
* - * @see #getShortValue + * @see #getShortValue(short) * @param holder the short data containing the bits we're * interested in * @param value the new value for the specified bits * @return the value of holder with the bits from the value * parameter replacing the old bits */ - public short setShortValue(final short holder, final short value) { + public short setShortValue(short holder, short value) { return (short) setValue(holder, value); } @@ -219,7 +182,7 @@ * @return the value of holder with the specified bits cleared * (set to0
)
*/
- public int clear(final int holder) {
+ public int clear(int holder) {
return holder & ~_mask;
}
@@ -231,7 +194,7 @@
* @return the value of holder with the specified bits cleared
* (set to 0
)
*/
- public short clearShort(final short holder) {
+ public short clearShort(short holder) {
return (short) clear(holder);
}
@@ -244,7 +207,7 @@
* @return the value of holder with the specified bits cleared
* (set to 0
)
*/
- public byte clearByte(final byte holder) {
+ public byte clearByte(byte holder) {
return (byte) clear(holder);
}
@@ -256,7 +219,7 @@
* @return the value of holder with the specified bits set
* to 1
*/
- public int set(final int holder) {
+ public int set(int holder) {
return holder | _mask;
}
@@ -268,7 +231,7 @@
* @return the value of holder with the specified bits set
* to 1
*/
- public short setShort(final short holder) {
+ public short setShort(short holder) {
return (short) set(holder);
}
@@ -281,7 +244,7 @@
* @return the value of holder with the specified bits set
* to 1
*/
- public byte setByte(final byte holder) {
+ public byte setByte(byte holder) {
return (byte) set(holder);
}
@@ -294,7 +257,7 @@
* @return the value of holder with the specified bits set or
* cleared
*/
- public int setBoolean(final int holder, final boolean flag) {
+ public int setBoolean(int holder, boolean flag) {
return flag ? set(holder) : clear(holder);
}
@@ -307,7 +270,7 @@
* @return the value of holder with the specified bits set or
* cleared
*/
- public short setShortBoolean(final short holder, final boolean flag) {
+ public short setShortBoolean(short holder, boolean flag) {
return flag ? setShort(holder) : clearShort(holder);
}
@@ -320,7 +283,7 @@
* @return the value of holder with the specified bits set or
* cleared
*/
- public byte setByteBoolean(final byte holder, final boolean flag) {
+ public byte setByteBoolean(byte holder, boolean flag) {
return flag ? setByte(holder) : clearByte(holder);
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/BooleanUtils.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/BooleanUtils.java (.../BooleanUtils.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/BooleanUtils.java (.../BooleanUtils.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,55 +1,18 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * null
input.
* Each method documents its behaviour in more detail.
*
- * @author Stephen Colebourne
+ * #ThreadSafe#
+ * @author Apache Software Foundation * @author Matthew Hawthorne * @author Gary Gregory * @since 2.0 @@ -78,6 +42,7 @@ * to operate. */ public BooleanUtils() { + super(); } // Boolean utilities @@ -86,6 +51,12 @@ *Negates the specified boolean.
* *If null
is passed in, null
will be returned.
+ * BooleanUtils.negate(Boolean.TRUE) = Boolean.FALSE; + * BooleanUtils.negate(Boolean.FALSE) = Boolean.TRUE; + * BooleanUtils.negate(null) = null; + ** * @param bool the Boolean to negate, may be null * @return the negated Boolean, or
null
if null
input
@@ -100,21 +71,111 @@
// boolean Boolean methods
//-----------------------------------------------------------------------
/**
+ * Checks if a Boolean
value is true
,
+ * handling null
by returning false
.
+ * BooleanUtils.isTrue(Boolean.TRUE) = true + * BooleanUtils.isTrue(Boolean.FALSE) = false + * BooleanUtils.isTrue(null) = false + *+ * + * @param bool the boolean to check, null returns
false
+ * @return true
only if the input is non-null and true
+ * @since 2.1
+ */
+ public static boolean isTrue(Boolean bool) {
+ if (bool == null) {
+ return false;
+ }
+ return bool.booleanValue() ? true : false;
+ }
+
+ /**
+ * Checks if a Boolean
value is not true
,
+ * handling null
by returning true
.
+ * BooleanUtils.isNotTrue(Boolean.TRUE) = false + * BooleanUtils.isNotTrue(Boolean.FALSE) = true + * BooleanUtils.isNotTrue(null) = true + *+ * + * @param bool the boolean to check, null returns
true
+ * @return true
if the input is null or false
+ * @since 2.3
+ */
+ public static boolean isNotTrue(Boolean bool) {
+ return !isTrue(bool);
+ }
+
+ /**
+ * Checks if a Boolean
value is false
,
+ * handling null
by returning false
.
+ * BooleanUtils.isFalse(Boolean.TRUE) = false + * BooleanUtils.isFalse(Boolean.FALSE) = true + * BooleanUtils.isFalse(null) = false + *+ * + * @param bool the boolean to check, null returns
false
+ * @return true
only if the input is non-null and false
+ * @since 2.1
+ */
+ public static boolean isFalse(Boolean bool) {
+ if (bool == null) {
+ return false;
+ }
+ return bool.booleanValue() ? false : true;
+ }
+
+ /**
+ * Checks if a Boolean
value is not false
,
+ * handling null
by returning true
.
+ * BooleanUtils.isNotFalse(Boolean.TRUE) = true + * BooleanUtils.isNotFalse(Boolean.FALSE) = false + * BooleanUtils.isNotFalse(null) = true + *+ * + * @param bool the boolean to check, null returns
true
+ * @return true
if the input is null or true
+ * @since 2.3
+ */
+ public static boolean isNotFalse(Boolean bool) {
+ return !isFalse(bool);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
* Boolean factory that avoids creating new Boolean objecs all the time.
* *This method was added to JDK1.4 but is available here for earlier JDKs.
- * + * + *+ * BooleanUtils.toBooleanObject(false) = Boolean.FALSE + * BooleanUtils.toBooleanObject(true) = Boolean.TRUE + *+ * * @param bool the boolean to convert * @return Boolean.TRUE or Boolean.FALSE as appropriate */ public static Boolean toBooleanObject(boolean bool) { - return (bool ? Boolean.TRUE : Boolean.FALSE); + return bool ? Boolean.TRUE : Boolean.FALSE; } /** *
Converts a Boolean to a boolean handling null
* by returning false
.
+ * BooleanUtils.toBoolean(Boolean.TRUE) = true + * BooleanUtils.toBoolean(Boolean.FALSE) = false + * BooleanUtils.toBoolean(null) = false + *+ * * @param bool the boolean to convert * @return
true
or false
,
* null
returns false
@@ -123,12 +184,18 @@
if (bool == null) {
return false;
}
- return (bool.booleanValue() ? true : false);
+ return bool.booleanValue() ? true : false;
}
/**
* Converts a Boolean to a boolean handling null
.
+ * BooleanUtils.toBooleanDefaultIfNull(Boolean.TRUE, false) = true + * BooleanUtils.toBooleanDefaultIfNull(Boolean.FALSE, true) = false + * BooleanUtils.toBooleanDefaultIfNull(null, true) = true + *+ * * @param bool the boolean to convert * @param valueIfNull the boolean value to return if
null
* @return true
or false
@@ -137,7 +204,7 @@
if (bool == null) {
return valueIfNull;
}
- return (bool.booleanValue() ? true : false);
+ return bool.booleanValue() ? true : false;
}
// Integer to Boolean methods
@@ -146,32 +213,50 @@
* Converts an int to a boolean using the convention that zero
* is false
.
+ * BooleanUtils.toBoolean(0) = false + * BooleanUtils.toBoolean(1) = true + * BooleanUtils.toBoolean(2) = true + *+ * * @param value the int to convert * @return
true
if non-zero, false
* if zero
*/
public static boolean toBoolean(int value) {
- return (value == 0 ? false : true);
+ return value == 0 ? false : true;
}
/**
* Converts an int to a Boolean using the convention that zero
* is false
.
+ * BooleanUtils.toBoolean(0) = Boolean.FALSE + * BooleanUtils.toBoolean(1) = Boolean.TRUE + * BooleanUtils.toBoolean(2) = Boolean.TRUE + *+ * * @param value the int to convert * @return Boolean.TRUE if non-zero, Boolean.FALSE if zero, *
null
if null
*/
public static Boolean toBooleanObject(int value) {
- return (value == 0 ? Boolean.FALSE : Boolean.TRUE);
+ return value == 0 ? Boolean.FALSE : Boolean.TRUE;
}
/**
* Converts an Integer to a Boolean using the convention that zero
* is false
.
null
will be converted to null
.
+ * BooleanUtils.toBoolean(new Integer(0)) = Boolean.FALSE + * BooleanUtils.toBoolean(new Integer(1)) = Boolean.TRUE + * BooleanUtils.toBoolean(new Integer(null)) = null + *+ * * @param value the Integer to convert * @return Boolean.TRUE if non-zero, Boolean.FALSE if zero, *
null
if null
input
@@ -180,12 +265,19 @@
if (value == null) {
return null;
}
- return (value.intValue() == 0 ? Boolean.FALSE : Boolean.TRUE);
+ return value.intValue() == 0 ? Boolean.FALSE : Boolean.TRUE;
}
/**
* Converts an int to a boolean specifying the conversion values.
* + *+ * BooleanUtils.toBoolean(0, 1, 0) = false + * BooleanUtils.toBoolean(1, 1, 0) = true + * BooleanUtils.toBoolean(2, 1, 2) = false + * BooleanUtils.toBoolean(2, 2, 0) = true + *+ * * @param value the Integer to convert * @param trueValue the value to match for
true
* @param falseValue the value to match for false
@@ -205,6 +297,14 @@
/**
* Converts an Integer to a boolean specifying the conversion values.
* + *+ * BooleanUtils.toBoolean(new Integer(0), new Integer(1), new Integer(0)) = false + * BooleanUtils.toBoolean(new Integer(1), new Integer(1), new Integer(0)) = true + * BooleanUtils.toBoolean(new Integer(2), new Integer(1), new Integer(2)) = false + * BooleanUtils.toBoolean(new Integer(2), new Integer(2), new Integer(0)) = true + * BooleanUtils.toBoolean(null, null, new Integer(0)) = true + *+ * * @param value the Integer to convert * @param trueValue the value to match for
true
,
* may be null
@@ -232,6 +332,12 @@
/**
* Converts an int to a Boolean specifying the conversion values.
* + *+ * BooleanUtils.toBooleanObject(0, 0, 2, 3) = Boolean.TRUE + * BooleanUtils.toBooleanObject(2, 1, 2, 3) = Boolean.FALSE + * BooleanUtils.toBooleanObject(3, 1, 2, 3) = null + *+ * * @param value the Integer to convert * @param trueValue the value to match for
true
* @param falseValue the value to match for false
@@ -254,6 +360,12 @@
/**
* Converts an Integer to a Boolean specifying the conversion values.
* + *+ * BooleanUtils.toBooleanObject(new Integer(0), new Integer(0), new Integer(2), new Integer(3)) = Boolean.TRUE + * BooleanUtils.toBooleanObject(new Integer(2), new Integer(1), new Integer(2), new Integer(3)) = Boolean.FALSE + * BooleanUtils.toBooleanObject(new Integer(3), new Integer(1), new Integer(2), new Integer(3)) = null + *+ * * @param value the Integer to convert * @param trueValue the value to match for
true
,
* may be null
@@ -289,56 +401,82 @@
/**
* Converts a boolean to an int using the convention that
* zero
is false
.
+ * BooleanUtils.toInteger(true) = 1 + * BooleanUtils.toInteger(false) = 0 + *+ * * @param bool the boolean to convert * @return one if
true
, zero if false
*/
public static int toInteger(boolean bool) {
- return (bool ? 1 : 0);
+ return bool ? 1 : 0;
}
/**
* Converts a boolean to an Integer using the convention that
* zero
is false
.
+ * BooleanUtils.toIntegerObject(true) = new Integer(1) + * BooleanUtils.toIntegerObject(false) = new Integer(0) + *+ * * @param bool the boolean to convert * @return one if
true
, zero if false
*/
public static Integer toIntegerObject(boolean bool) {
- return (bool ? NumberUtils.INTEGER_ONE : NumberUtils.INTEGER_ZERO);
+ return bool ? NumberUtils.INTEGER_ONE : NumberUtils.INTEGER_ZERO;
}
/**
* Converts a Boolean to a Integer using the convention that
* zero
is false
.
null
will be converted to null
.
+ * BooleanUtils.toIntegerObject(Boolean.TRUE) = new Integer(1) + * BooleanUtils.toIntegerObject(Boolean.FALSE) = new Integer(0) + *+ * * @param bool the Boolean to convert * @return one if Boolean.TRUE, zero if Boolean.FALSE,
null
if null
*/
public static Integer toIntegerObject(Boolean bool) {
if (bool == null) {
return null;
}
- return (bool.booleanValue() ? NumberUtils.INTEGER_ONE : NumberUtils.INTEGER_ZERO);
+ return bool.booleanValue() ? NumberUtils.INTEGER_ONE : NumberUtils.INTEGER_ZERO;
}
/**
* Converts a boolean to an int specifying the conversion values.
* + *+ * BooleanUtils.toInteger(true, 1, 0) = 1 + * BooleanUtils.toInteger(false, 1, 0) = 0 + *+ * * @param bool the to convert * @param trueValue the value to return if
true
* @param falseValue the value to return if false
* @return the appropriate value
*/
public static int toInteger(boolean bool, int trueValue, int falseValue) {
- return (bool ? trueValue : falseValue);
+ return bool ? trueValue : falseValue;
}
/**
* Converts a Boolean to an int specifying the conversion values.
* + *+ * BooleanUtils.toInteger(Boolean.TRUE, 1, 0, 2) = 1 + * BooleanUtils.toInteger(Boolean.FALSE, 1, 0, 2) = 0 + * BooleanUtils.toInteger(null, 1, 0, 2) = 2 + *+ * * @param bool the Boolean to convert * @param trueValue the value to return if
true
* @param falseValue the value to return if false
@@ -349,12 +487,17 @@
if (bool == null) {
return nullValue;
}
- return (bool.booleanValue() ? trueValue : falseValue);
+ return bool.booleanValue() ? trueValue : falseValue;
}
/**
* Converts a boolean to an Integer specifying the conversion values.
* + *+ * BooleanUtils.toIntegerObject(true, new Integer(1), new Integer(0)) = new Integer(1) + * BooleanUtils.toIntegerObject(false, new Integer(1), new Integer(0)) = new Integer(0) + *+ * * @param bool the to convert * @param trueValue the value to return if
true
,
* may be null
@@ -363,12 +506,18 @@
* @return the appropriate value
*/
public static Integer toIntegerObject(boolean bool, Integer trueValue, Integer falseValue) {
- return (bool ? trueValue : falseValue);
+ return bool ? trueValue : falseValue;
}
/**
* Converts a Boolean to an Integer specifying the conversion values.
* + *+ * BooleanUtils.toIntegerObject(Boolean.TRUE, new Integer(1), new Integer(0), new Integer(2)) = new Integer(1) + * BooleanUtils.toIntegerObject(Boolean.FALSE, new Integer(1), new Integer(0), new Integer(2)) = new Integer(0) + * BooleanUtils.toIntegerObject(null, new Integer(1), new Integer(0), new Integer(2)) = new Integer(2) + *+ * * @param bool the Boolean to convert * @param trueValue the value to return if
true
,
* may be null
@@ -382,7 +531,7 @@
if (bool == null) {
return nullValue;
}
- return (bool.booleanValue() ? trueValue : falseValue);
+ return bool.booleanValue() ? trueValue : falseValue;
}
// String to Boolean methods
@@ -396,31 +545,126 @@
* (case insensitive) will return false
.
* Otherwise, null
is returned.
*
+ * + * BooleanUtils.toBooleanObject(null) = null + * BooleanUtils.toBooleanObject("true") = Boolean.TRUE + * BooleanUtils.toBooleanObject("false") = Boolean.FALSE + * BooleanUtils.toBooleanObject("on") = Boolean.TRUE + * BooleanUtils.toBooleanObject("ON") = Boolean.TRUE + * BooleanUtils.toBooleanObject("off") = Boolean.FALSE + * BooleanUtils.toBooleanObject("oFf") = Boolean.FALSE + * BooleanUtils.toBooleanObject("blue") = null + *+ * * @param str the String to check * @return the Boolean value of the string, *
null
if no match or null
input
*/
public static Boolean toBooleanObject(String str) {
- if ("true".equalsIgnoreCase(str)) {
+ // Previously used equalsIgnoreCase, which was fast for interned 'true'.
+ // Non interned 'true' matched 15 times slower.
+ //
+ // Optimisation provides same performance as before for interned 'true'.
+ // Similar performance for null, 'false', and other strings not length 2/3/4.
+ // 'true'/'TRUE' match 4 times slower, 'tRUE'/'True' 7 times slower.
+ if (str == "true") {
return Boolean.TRUE;
- } else if ("false".equalsIgnoreCase(str)) {
- return Boolean.FALSE;
- } else if ("on".equalsIgnoreCase(str)) {
- return Boolean.TRUE;
- } else if ("off".equalsIgnoreCase(str)) {
- return Boolean.FALSE;
- } else if ("yes".equalsIgnoreCase(str)) {
- return Boolean.TRUE;
- } else if ("no".equalsIgnoreCase(str)) {
- return Boolean.FALSE;
}
- // no match
+ if (str == null) {
+ return null;
+ }
+ switch (str.length()) {
+ case 1: {
+ char ch0 = str.charAt(0);
+ if ((ch0 == 'y' || ch0 == 'Y') ||
+ (ch0 == 't' || ch0 == 'T'))
+ {
+ return Boolean.TRUE;
+ }
+ if ((ch0 == 'n' || ch0 == 'N') ||
+ (ch0 == 'f' || ch0 == 'F'))
+ {
+ return Boolean.FALSE;
+ }
+ break;
+ }
+ case 2: {
+ char ch0 = str.charAt(0);
+ char ch1 = str.charAt(1);
+ if ((ch0 == 'o' || ch0 == 'O') &&
+ (ch1 == 'n' || ch1 == 'N') )
+ {
+ return Boolean.TRUE;
+ }
+ if ((ch0 == 'n' || ch0 == 'N') &&
+ (ch1 == 'o' || ch1 == 'O') )
+ {
+ return Boolean.FALSE;
+ }
+ break;
+ }
+ case 3: {
+ char ch0 = str.charAt(0);
+ char ch1 = str.charAt(1);
+ char ch2 = str.charAt(2);
+ if ((ch0 == 'y' || ch0 == 'Y') &&
+ (ch1 == 'e' || ch1 == 'E') &&
+ (ch2 == 's' || ch2 == 'S') )
+ {
+ return Boolean.TRUE;
+ }
+ if ((ch0 == 'o' || ch0 == 'O') &&
+ (ch1 == 'f' || ch1 == 'F') &&
+ (ch2 == 'f' || ch2 == 'F') )
+ {
+ return Boolean.FALSE;
+ }
+ break;
+ }
+ case 4: {
+ char ch0 = str.charAt(0);
+ char ch1 = str.charAt(1);
+ char ch2 = str.charAt(2);
+ char ch3 = str.charAt(3);
+ if ((ch0 == 't' || ch0 == 'T') &&
+ (ch1 == 'r' || ch1 == 'R') &&
+ (ch2 == 'u' || ch2 == 'U') &&
+ (ch3 == 'e' || ch3 == 'E') )
+ {
+ return Boolean.TRUE;
+ }
+ break;
+ }
+ case 5: {
+ char ch0 = str.charAt(0);
+ char ch1 = str.charAt(1);
+ char ch2 = str.charAt(2);
+ char ch3 = str.charAt(3);
+ char ch4 = str.charAt(4);
+ if ((ch0 == 'f' || ch0 == 'F') &&
+ (ch1 == 'a' || ch1 == 'A') &&
+ (ch2 == 'l' || ch2 == 'L') &&
+ (ch3 == 's' || ch3 == 'S') &&
+ (ch4 == 'e' || ch4 == 'E') )
+ {
+ return Boolean.FALSE;
+ }
+ break;
+ }
+ }
+
return null;
}
/**
* Converts a String to a Boolean throwing an exception if no match.
* + *+ * BooleanUtils.toBooleanObject("true", "true", "false", "null") = Boolean.TRUE + * BooleanUtils.toBooleanObject("false", "true", "false", "null") = Boolean.FALSE + * BooleanUtils.toBooleanObject("null", "true", "false", "null") = null + *+ * * @param str the String to check * @param trueString the String to match for
true
* (case sensitive), may be null
@@ -429,7 +673,10 @@
* @param nullString the String to match for null
* (case sensitive), may be null
* @return the Boolean value of the string,
- * null
if no match or null
input
+ * null
if either the String matches nullString
+ * or if null
input and nullString
is
+ * null
+ * @throws IllegalArgumentException if the String doesn't match
*/
public static Boolean toBooleanObject(String str, String trueString, String falseString, String nullString) {
if (str == null) {
@@ -454,32 +701,44 @@
// String to boolean methods
//-----------------------------------------------------------------------
/**
- * Converts a String to a boolean.
+ *Converts a String to a boolean (optimised for performance).
* *'true'
, 'on'
or 'yes'
* (case insensitive) will return true
. Otherwise,
* false
is returned.
This method performs 4 times faster (JDK1.4) than
+ * Boolean.valueOf(String)
. However, this method accepts
+ * 'on' and 'yes' as true values.
*
+ *
+ * BooleanUtils.toBoolean(null) = false + * BooleanUtils.toBoolean("true") = true + * BooleanUtils.toBoolean("TRUE") = true + * BooleanUtils.toBoolean("tRUe") = true + * BooleanUtils.toBoolean("on") = true + * BooleanUtils.toBoolean("yes") = true + * BooleanUtils.toBoolean("false") = false + * BooleanUtils.toBoolean("x gti") = false + *+ * * @param str the String to check - * @return the boolean value of the string,
false
if no match
+ * @return the boolean value of the string, false
if no match or the String is null
*/
public static boolean toBoolean(String str) {
- if ("true".equalsIgnoreCase(str)) {
- return true;
- } else if ("on".equalsIgnoreCase(str)) {
- return true;
- } else if ("yes".equalsIgnoreCase(str)) {
- return true;
- }
- // no match
- return false;
+ return toBoolean(toBooleanObject(str));
}
-
+
/**
* Converts a String to a Boolean throwing an exception if no match found.
* *null is returned if there is no match.
* + *+ * BooleanUtils.toBoolean("true", "true", "false") = true + * BooleanUtils.toBoolean("false", "true", "false") = false + *+ * * @param str the String to check * @param trueString the String to match for
true
* (case sensitive), may be null
@@ -510,6 +769,12 @@
* Converts a Boolean to a String returning 'true'
,
* 'false'
, or null
.
+ * BooleanUtils.toStringTrueFalse(Boolean.TRUE) = "true" + * BooleanUtils.toStringTrueFalse(Boolean.FALSE) = "false" + * BooleanUtils.toStringTrueFalse(null) = null; + *+ * * @param bool the Boolean to check * @return
'true'
, 'false'
,
* or null
@@ -522,6 +787,12 @@
* Converts a Boolean to a String returning 'on'
,
* 'off'
, or null
.
+ * BooleanUtils.toStringOnOff(Boolean.TRUE) = "on" + * BooleanUtils.toStringOnOff(Boolean.FALSE) = "off" + * BooleanUtils.toStringOnOff(null) = null; + *+ * * @param bool the Boolean to check * @return
'on'
, 'off'
,
* or null
@@ -534,6 +805,12 @@
* Converts a Boolean to a String returning 'yes'
,
* 'no'
, or null
.
+ * BooleanUtils.toStringYesNo(Boolean.TRUE) = "yes" + * BooleanUtils.toStringYesNo(Boolean.FALSE) = "no" + * BooleanUtils.toStringYesNo(null) = null; + *+ * * @param bool the Boolean to check * @return
'yes'
, 'no'
,
* or null
@@ -545,6 +822,12 @@
/**
* Converts a Boolean to a String returning one of the input Strings.
* + *+ * BooleanUtils.toString(Boolean.TRUE, "true", "false", null) = "true" + * BooleanUtils.toString(Boolean.FALSE, "true", "false", null) = "false" + * BooleanUtils.toString(null, "true", "false", null) = null; + *+ * * @param bool the Boolean to check * @param trueString the String to return if
true
,
* may be null
@@ -558,7 +841,7 @@
if (bool == null) {
return nullString;
}
- return (bool.booleanValue() ? trueString : falseString);
+ return bool.booleanValue() ? trueString : falseString;
}
// boolean to String methods
@@ -567,6 +850,11 @@
* Converts a boolean to a String returning 'true'
* or 'false'
.
+ * BooleanUtils.toStringTrueFalse(true) = "true" + * BooleanUtils.toStringTrueFalse(false) = "false" + *+ * * @param bool the Boolean to check * @return
'true'
, 'false'
,
* or null
@@ -579,6 +867,11 @@
* Converts a boolean to a String returning 'on'
* or 'off'
.
+ * BooleanUtils.toStringOnOff(true) = "on" + * BooleanUtils.toStringOnOff(false) = "off" + *+ * * @param bool the Boolean to check * @return
'on'
, 'off'
,
* or null
@@ -591,6 +884,11 @@
* Converts a boolean to a String returning 'yes'
* or 'no'
.
+ * BooleanUtils.toStringYesNo(true) = "yes" + * BooleanUtils.toStringYesNo(false) = "no" + *+ * * @param bool the Boolean to check * @return
'yes'
, 'no'
,
* or null
@@ -602,6 +900,11 @@
/**
* Converts a boolean to a String returning one of the input Strings.
* + *+ * BooleanUtils.toString(true, "true", "false") = "true" + * BooleanUtils.toString(false, "true", "false") = "false" + *+ * * @param bool the Boolean to check * @param trueString the String to return if
true
,
* may be null
@@ -610,14 +913,20 @@
* @return one of the two input Strings
*/
public static String toString(boolean bool, String trueString, String falseString) {
- return (bool ? trueString : falseString);
+ return bool ? trueString : falseString;
}
// xor methods
// ----------------------------------------------------------------------
/**
* Performs an xor on a set of booleans.
- * + * + *+ * BooleanUtils.xor(new boolean[] { true, true }) = false + * BooleanUtils.xor(new boolean[] { false, false }) = false + * BooleanUtils.xor(new boolean[] { true, false }) = true + *+ * * @param array an array of
booleans
* @return true
if the xor is successful.
* @throws IllegalArgumentException if array
is null
@@ -652,6 +961,12 @@
/**
* Performs an xor on an array of Booleans.
*
+ *
+ * BooleanUtils.xor(new Boolean[] { Boolean.TRUE, Boolean.TRUE }) = Boolean.FALSE
+ * BooleanUtils.xor(new Boolean[] { Boolean.FALSE, Boolean.FALSE }) = Boolean.FALSE
+ * BooleanUtils.xor(new Boolean[] { Boolean.TRUE, Boolean.FALSE }) = Boolean.TRUE
+ *
+ *
* @param array an array of Booleans
* @return true
if the xor is successful.
* @throws IllegalArgumentException if array
is null
@@ -668,9 +983,9 @@
try {
primitive = ArrayUtils.toPrimitive(array);
} catch (NullPointerException ex) {
- throw new IllegalArgumentException("The array must not conatin any null elements");
+ throw new IllegalArgumentException("The array must not contain any null elements");
}
- return (xor(primitive) ? Boolean.TRUE : Boolean.FALSE);
+ return xor(primitive) ? Boolean.TRUE : Boolean.FALSE;
}
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/CharEncoding.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/CharEncoding.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/CharEncoding.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.commons.lang;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ *
+ * Character encoding names required of every implementation of the Java platform.
+ *
+ *
+ *
+ * According to JRE character
+ * encoding names:
+ *
+ * Every implementation of the Java platform is required to support the following character encodings. Consult the
+ * release documentation for your implementation to see if any other encodings are supported.
+ *
+ *
+ *
+ * @see JRE character encoding
+ * names
+ * @author Apache Software Foundation
+ * @since 2.1
+ * @version $Id$
+ */
+public class CharEncoding {
+
+ /**
+ *
+ * ISO Latin Alphabet #1, also known as ISO-LATIN-1.
+ *
+ *
+ * Every implementation of the Java platform is required to support this character encoding.
+ *
+ *
+ * @see JRE character
+ * encoding names
+ */
+ public static final String ISO_8859_1 = "ISO-8859-1";
+
+ /**
+ *
+ * Seven-bit ASCII, also known as ISO646-US, also known as the Basic Latin block of the Unicode character set.
+ *
+ *
+ * Every implementation of the Java platform is required to support this character encoding.
+ *
+ *
+ * @see JRE character
+ * encoding names
+ */
+ public static final String US_ASCII = "US-ASCII";
+
+ /**
+ *
+ * Sixteen-bit Unicode Transformation Format, byte order specified by a mandatory initial byte-order mark (either
+ * order accepted on input, big-endian used on output).
+ *
+ *
+ * Every implementation of the Java platform is required to support this character encoding.
+ *
+ *
+ * @see JRE character
+ * encoding names
+ */
+ public static final String UTF_16 = "UTF-16";
+
+ /**
+ *
+ * Sixteen-bit Unicode Transformation Format, big-endian byte order.
+ *
+ *
+ * Every implementation of the Java platform is required to support this character encoding.
+ *
+ *
+ * @see JRE character
+ * encoding names
+ */
+ public static final String UTF_16BE = "UTF-16BE";
+
+ /**
+ *
+ * Sixteen-bit Unicode Transformation Format, little-endian byte order.
+ *
+ *
+ * Every implementation of the Java platform is required to support this character encoding.
+ *
+ *
+ * @see JRE character
+ * encoding names
+ */
+ public static final String UTF_16LE = "UTF-16LE";
+
+ /**
+ *
+ * Eight-bit Unicode Transformation Format.
+ *
+ *
+ * Every implementation of the Java platform is required to support this character encoding.
+ *
+ *
+ * @see JRE character
+ * encoding names
+ */
+ public static final String UTF_8 = "UTF-8";
+
+ /**
+ *
+ * Returns whether the named charset is supported.
+ *
+ *
+ * This is similar to
+ * java.nio.charset.Charset.isSupported(String)
+ *
+ *
+ * @param name
+ * the name of the requested charset; may be either a canonical name or an alias
+ * @return true
if, and only if, support for the named charset is available in the current Java
+ * virtual machine
+ *
+ * @see JRE character
+ * encoding names
+ */
+ public static boolean isSupported(String name) {
+ if (name == null) {
+ return false;
+ }
+ try {
+ new String(ArrayUtils.EMPTY_BYTE_ARRAY, name);
+ } catch (UnsupportedEncodingException e) {
+ return false;
+ }
+ return true;
+ }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/CharRange.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/CharRange.java (.../CharRange.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/CharRange.java (.../CharRange.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,75 +1,46 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang;
import java.io.Serializable;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import org.apache.commons.lang.text.StrBuilder;
+
/**
* A contiguous range of characters, optionally negated.
*
* Instances are immutable.
*
- * @author Henri Yandell
- * @author Stephen Colebourne
+ * #ThreadSafe#
+ * @author Apache Software Foundation
* @author Chris Feldhacker
* @author Gary Gregory
* @since 1.0
* @version $Id$
*/
public final class CharRange implements Serializable {
- /** Serialization lock, Lang version 2.0. */
+ /**
+ * Required for serialization support. Lang version 2.0.
+ *
+ * @see java.io.Serializable
+ */
private static final long serialVersionUID = 8270183163158333422L;
/** The first character, inclusive, in the range. */
@@ -82,12 +53,64 @@
/** Cached toString. */
private transient String iToString;
+ // Static
//-----------------------------------------------------------------------
/**
* Constructs a CharRange
over a single character.
*
* @param ch only character in this range
+ * @return the new CharRange object
+ * @see CharRange#CharRange(char, char, boolean)
+ * @since 2.5
*/
+ public static CharRange is(char ch) {
+ return new CharRange(ch, ch, false);
+ }
+
+ /**
+ * Constructs a negated CharRange
over a single character.
+ *
+ * @param ch only character in this range
+ * @return the new CharRange object
+ * @see CharRange#CharRange(char, char, boolean)
+ * @since 2.5
+ */
+ public static CharRange isNot(char ch) {
+ return new CharRange(ch, ch, true);
+ }
+
+ /**
+ * Constructs a CharRange
over a set of characters.
+ *
+ * @param start first character, inclusive, in this range
+ * @param end last character, inclusive, in this range
+ * @return the new CharRange object
+ * @see CharRange#CharRange(char, char, boolean)
+ * @since 2.5
+ */
+ public static CharRange isIn(char start, char end) {
+ return new CharRange(start, end, false);
+ }
+
+ /**
+ * Constructs a negated CharRange
over a set of characters.
+ *
+ * @param start first character, inclusive, in this range
+ * @param end last character, inclusive, in this range
+ * @return the new CharRange object
+ * @see CharRange#CharRange(char, char, boolean)
+ * @since 2.5
+ */
+ public static CharRange isNotIn(char start, char end) {
+ return new CharRange(start, end, true);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Constructs a CharRange
over a single character.
+ *
+ * @param ch only character in this range
+ */
public CharRange(char ch) {
this(ch, ch, false);
}
@@ -183,7 +206,7 @@
* @return true
if this range contains the input character
*/
public boolean contains(char ch) {
- return ((ch >= start && ch <= end) != negated);
+ return (ch >= start && ch <= end) != negated;
}
/**
@@ -200,17 +223,14 @@
}
if (negated) {
if (range.negated) {
- return (start >= range.start && end <= range.end);
- } else {
- return (range.end < start || range.start > end);
+ return start >= range.start && end <= range.end;
}
- } else {
- if (range.negated) {
- return (start == 0 && end == Character.MAX_VALUE);
- } else {
- return (start <= range.start && end >= range.end);
- }
+ return range.end < start || range.start > end;
}
+ if (range.negated) {
+ return start == 0 && end == Character.MAX_VALUE;
+ }
+ return start <= range.start && end >= range.end;
}
// Basics
@@ -230,11 +250,11 @@
return false;
}
CharRange other = (CharRange) obj;
- return (start == other.start && end == other.end && negated == other.negated);
+ return start == other.start && end == other.end && negated == other.negated;
}
/**
- * Gets a hashCode compatable with the equals method.
+ * Gets a hashCode compatible with the equals method.
*
* @return a suitable hashCode
*/
@@ -249,7 +269,7 @@
*/
public String toString() {
if (iToString == null) {
- StringBuffer buf = new StringBuffer(4);
+ StrBuilder buf = new StrBuilder(4);
if (isNegated()) {
buf.append('^');
}
@@ -262,5 +282,110 @@
}
return iToString;
}
-
+
+ // Expansions
+ //-----------------------------------------------------------------------
+ /**
+ * Returns an iterator which can be used to walk through the characters described by this range.
+ *
+ * #NotThreadSafe# the iterator is not threadsafe
+ * @return an iterator to the chars represented by this range
+ * @since 2.5
+ */
+ public Iterator iterator() {
+ return new CharacterIterator(this);
+ }
+
+ /**
+ * Character {@link Iterator}.
+ * #NotThreadSafe#
+ */
+ private static class CharacterIterator implements Iterator {
+ /** The current character */
+ private char current;
+
+ private final CharRange range;
+ private boolean hasNext;
+
+ /**
+ * Construct a new iterator for the character range.
+ *
+ * @param r The character range
+ */
+ private CharacterIterator(CharRange r) {
+ range = r;
+ hasNext = true;
+
+ if (range.negated) {
+ if (range.start == 0) {
+ if (range.end == Character.MAX_VALUE) {
+ // This range is an empty set
+ hasNext = false;
+ } else {
+ current = (char) (range.end + 1);
+ }
+ } else {
+ current = 0;
+ }
+ } else {
+ current = range.start;
+ }
+ }
+
+ /**
+ * Prepare the next character in the range.
+ */
+ private void prepareNext() {
+ if (range.negated) {
+ if (current == Character.MAX_VALUE) {
+ hasNext = false;
+ } else if (current + 1 == range.start) {
+ if (range.end == Character.MAX_VALUE) {
+ hasNext = false;
+ } else {
+ current = (char) (range.end + 1);
+ }
+ } else {
+ current = (char) (current + 1);
+ }
+ } else if (current < range.end) {
+ current = (char) (current + 1);
+ } else {
+ hasNext = false;
+ }
+ }
+
+ /**
+ * Has the iterator not reached the end character yet?
+ *
+ * @return true
if the iterator has yet to reach the character date
+ */
+ public boolean hasNext() {
+ return hasNext;
+ }
+
+ /**
+ * Return the next character in the iteration
+ *
+ * @return Character
for the next character
+ */
+ public Object next() {
+ if (hasNext == false) {
+ throw new NoSuchElementException();
+ }
+ char cur = current;
+ prepareNext();
+ return new Character(cur);
+ }
+
+ /**
+ * Always throws UnsupportedOperationException.
+ *
+ * @throws UnsupportedOperationException
+ * @see java.util.Iterator#remove()
+ */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/CharSet.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/CharSet.java (.../CharSet.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/CharSet.java (.../CharSet.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,59 +1,23 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang;
import java.io.Serializable;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -65,8 +29,8 @@
*
* Instances are immutable, but instances of subclasses may not be.
*
- * @author Henri Yandell
- * @author Stephen Colebourne
+ * #ThreadSafe#
+ * @author Apache Software Foundation
* @author Phil Steitz
* @author Pete Gieser
* @author Gary Gregory
@@ -75,7 +39,11 @@
*/
public class CharSet implements Serializable {
- /** Serialization lock, Lang version 2.0. */
+ /**
+ * Required for serialization support. Lang version 2.0.
+ *
+ * @see java.io.Serializable
+ */
private static final long serialVersionUID = 5947847346149275958L;
/**
@@ -110,10 +78,10 @@
/**
* A Map of the common cases used in the factory.
- * Subclasses can add more common patterns if desired.
+ * Subclasses can add more common patterns if desired
* @since 2.0
*/
- protected static final Map COMMON = new HashMap();
+ protected static final Map COMMON = Collections.synchronizedMap(new HashMap());
static {
COMMON.put(null, EMPTY);
@@ -126,7 +94,7 @@
}
/** The set of CharRange objects. */
- private Set set = new HashSet();
+ private final Set set = Collections.synchronizedSet(new HashSet());
//-----------------------------------------------------------------------
/**
@@ -180,6 +148,21 @@
return new CharSet(setStr);
}
+ /**
+ * Constructs a new CharSet using the set syntax.
+ * Each string is merged in with the set.
+ *
+ * @param setStrs Strings to merge into the initial set, may be null
+ * @return a CharSet instance
+ * @since 2.4
+ */
+ public static CharSet getInstance(String[] setStrs) {
+ if (setStrs == null) {
+ return null;
+ }
+ return new CharSet(setStrs);
+ }
+
//-----------------------------------------------------------------------
/**
* Constructs a new CharSet using the set syntax.
@@ -224,19 +207,19 @@
int remainder = (len - pos);
if (remainder >= 4 && str.charAt(pos) == '^' && str.charAt(pos + 2) == '-') {
// negated range
- set.add(new CharRange(str.charAt(pos + 1), str.charAt(pos + 3), true));
+ set.add(CharRange.isNotIn(str.charAt(pos + 1), str.charAt(pos + 3)));
pos += 4;
} else if (remainder >= 3 && str.charAt(pos + 1) == '-') {
// range
- set.add(new CharRange(str.charAt(pos), str.charAt(pos + 2)));
+ set.add(CharRange.isIn(str.charAt(pos), str.charAt(pos + 2)));
pos += 3;
} else if (remainder >= 2 && str.charAt(pos) == '^') {
// negated char
- set.add(new CharRange(str.charAt(pos + 1), true));
+ set.add(CharRange.isNot(str.charAt(pos + 1)));
pos += 2;
} else {
// char
- set.add(new CharRange(str.charAt(pos)));
+ set.add(CharRange.is(str.charAt(pos)));
pos += 1;
}
}
@@ -292,11 +275,11 @@
return false;
}
CharSet other = (CharSet) obj;
- return (set.equals(other.set));
+ return set.equals(other.set);
}
/**
- * Gets a hashCode compatable with the equals method.
+ * Gets a hashCode compatible with the equals method.
*
* @return a suitable hashCode
* @since 2.0
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/CharSetUtils.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/CharSetUtils.java (.../CharSetUtils.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/CharSetUtils.java (.../CharSetUtils.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,68 +1,33 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang;
+import org.apache.commons.lang.text.StrBuilder;
+
/**
* Operations on CharSet
s.
*
* This class handles null
input gracefully.
* An exception will not be thrown for a null
input.
* Each method documents its behaviour in more detail.
*
+ * #ThreadSafe#
* @see CharSet
- * @author Henri Yandell
- * @author Stephen Colebourne
+ * @author Apache Software Foundation
* @author Phil Steitz
* @author Gary Gregory
* @since 1.0
@@ -78,6 +43,7 @@
* to operate.
*/
public CharSetUtils() {
+ super();
}
// Factory
@@ -89,7 +55,7 @@
*
* - "aeio" which implies 'a','e',..
* - "^e" implies not e.
- * - "ej-m" implies e,j->m. e,j,k,l,m.
+ * - "ej-m" implies e,j->m. e,j,k,l,m.
*
*
*
@@ -100,7 +66,7 @@
*
* @param set the set, may be null
* @return a CharSet instance, null
if null input
- * @deprecated Use {@link CharSet#getInstance(String)}.
+ * @deprecated Use {@link CharSet#getInstance(String[])}.
* Method will be removed in Commons Lang 3.0.
*/
public static CharSet evaluateSet(String[] set) {
@@ -113,7 +79,7 @@
// Squeeze
//-----------------------------------------------------------------------
/**
- * Squeezes any repititions of a character that is mentioned in the
+ *
Squeezes any repetitions of a character that is mentioned in the
* supplied set.
*
*
@@ -125,13 +91,13 @@
* CharSetUtils.squeeze("hello", "a-e") = "hello"
*
*
- * @see #evaluateSet(java.lang.String[]) for set-syntax.
+ * @see CharSet#getInstance(java.lang.String) for set-syntax.
* @param str the string to squeeze, may be null
* @param set the character set to use for manipulation, may be null
* @return modified String, null
if null string input
*/
public static String squeeze(String str, String set) {
- if (str == null || str.length() == 0 || set == null || set.length() == 0) {
+ if (StringUtils.isEmpty(str) || StringUtils.isEmpty(set)) {
return str;
}
String[] strs = new String[1];
@@ -140,25 +106,25 @@
}
/**
- * Squeezes any repititions of a character that is mentioned in the
+ *
Squeezes any repetitions of a character that is mentioned in the
* supplied set.
*
* An example is:
*
* - squeeze("hello", {"el"}) => "helo"
*
*
- * @see #evaluateSet(java.lang.String[]) for set-syntax.
+ * @see CharSet#getInstance(java.lang.String) for set-syntax.
* @param str the string to squeeze, may be null
* @param set the character set to use for manipulation, may be null
* @return modified String, null
if null string input
*/
public static String squeeze(String str, String[] set) {
- if (str == null || str.length() == 0 || set == null || set.length == 0) {
+ if (StringUtils.isEmpty(str) || ArrayUtils.isEmpty(set)) {
return str;
}
- CharSet chars = evaluateSet(set);
- StringBuffer buffer = new StringBuffer(str.length());
+ CharSet chars = CharSet.getInstance(set);
+ StrBuilder buffer = new StrBuilder(str.length());
char[] chrs = str.toCharArray();
int sz = chrs.length;
char lastChar = ' ';
@@ -191,13 +157,13 @@
* CharSetUtils.count("hello", "a-e") = 1
*
*
- * @see #evaluateSet(java.lang.String[]) for set-syntax.
+ * @see CharSet#getInstance(java.lang.String) for set-syntax.
* @param str String to count characters in, may be null
* @param set String set of characters to count, may be null
* @return character count, zero if null string input
*/
public static int count(String str, String set) {
- if (str == null || str.length() == 0 || set == null || set.length() == 0) {
+ if (StringUtils.isEmpty(str) || StringUtils.isEmpty(set)) {
return 0;
}
String[] strs = new String[1];
@@ -214,16 +180,16 @@
* count("hello", {"c-f", "o"}) returns 2.
*
*
- * @see #evaluateSet(java.lang.String[]) for set-syntax.
+ * @see CharSet#getInstance(java.lang.String) for set-syntax.
* @param str String to count characters in, may be null
* @param set String[] set of characters to count, may be null
* @return character count, zero if null string input
*/
public static int count(String str, String[] set) {
- if (str == null || str.length() == 0 || set == null || set.length == 0) {
+ if (StringUtils.isEmpty(str) || ArrayUtils.isEmpty(set)) {
return 0;
}
- CharSet chars = evaluateSet(set);
+ CharSet chars = CharSet.getInstance(set);
int count = 0;
char[] chrs = str.toCharArray();
int sz = chrs.length;
@@ -246,11 +212,11 @@
* CharSetUtils.keep("", *) = ""
* CharSetUtils.keep(*, null) = ""
* CharSetUtils.keep(*, "") = ""
- * CharSetUtils.keep("hello", "hl") = "hll"
- * CharSetUtils.keep("hello", "le") = "ell"
+ * CharSetUtils.keep("hello", "hl") = "hll"
+ * CharSetUtils.keep("hello", "le") = "ell"
*
*
- * @see #evaluateSet(java.lang.String[]) for set-syntax.
+ * @see CharSet#getInstance(java.lang.String) for set-syntax.
* @param str String to keep characters from, may be null
* @param set String set of characters to keep, may be null
* @return modified String, null
if null string input
@@ -260,7 +226,7 @@
if (str == null) {
return null;
}
- if (str.length() == 0 || set == null || set.length() == 0) {
+ if (str.length() == 0 || StringUtils.isEmpty(set)) {
return "";
}
String[] strs = new String[1];
@@ -275,10 +241,10 @@
* An example would be:
*
* - keep("hello", {"c-f", "o"})
- * returns "hll"
+ * returns "eo"
*
*
- * @see #evaluateSet(java.lang.String[]) for set-syntax.
+ * @see CharSet#getInstance(java.lang.String) for set-syntax.
* @param str String to keep characters from, may be null
* @param set String[] set of characters to keep, may be null
* @return modified String, null
if null string input
@@ -288,7 +254,7 @@
if (str == null) {
return null;
}
- if (str.length() == 0 || set == null || set.length == 0) {
+ if (str.length() == 0 || ArrayUtils.isEmpty(set)) {
return "";
}
return modify(str, set, true);
@@ -305,17 +271,17 @@
* CharSetUtils.delete("", *) = ""
* CharSetUtils.delete(*, null) = *
* CharSetUtils.delete(*, "") = *
- * CharSetUtils.delete("hello", "hl") = "hll"
- * CharSetUtils.delete("hello", "le") = "ell"
+ * CharSetUtils.delete("hello", "hl") = "eo"
+ * CharSetUtils.delete("hello", "le") = "ho"
*
*
- * @see #evaluateSet(java.lang.String[]) for set-syntax.
+ * @see CharSet#getInstance(java.lang.String) for set-syntax.
* @param str String to delete characters from, may be null
* @param set String set of characters to delete, may be null
* @return modified String, null
if null string input
*/
public static String delete(String str, String set) {
- if (str == null || str.length() == 0 || set == null || set.length() == 0) {
+ if (StringUtils.isEmpty(str) || StringUtils.isEmpty(set)) {
return str;
}
String[] strs = new String[1];
@@ -333,23 +299,30 @@
* "hll"
*
*
- * @see #evaluateSet(java.lang.String[]) for set-syntax.
+ * @see CharSet#getInstance(java.lang.String) for set-syntax.
* @param str String to delete characters from, may be null
* @param set String[] set of characters to delete, may be null
* @return modified String, null
if null string input
*/
public static String delete(String str, String[] set) {
- if (str == null || str.length() == 0 || set == null || set.length == 0) {
+ if (StringUtils.isEmpty(str) || ArrayUtils.isEmpty(set)) {
return str;
}
return modify(str, set, false);
}
//-----------------------------------------------------------------------
- // Implementation of delete and keep
+ /**
+ * Implementation of delete and keep
+ *
+ * @param str String to modify characters within
+ * @param set String[] set of characters to modify
+ * @param expect whether to evaluate on match, or non-match
+ * @return modified String
+ */
private static String modify(String str, String[] set, boolean expect) {
- CharSet chars = evaluateSet(set);
- StringBuffer buffer = new StringBuffer(str.length());
+ CharSet chars = CharSet.getInstance(set);
+ StrBuilder buffer = new StrBuilder(str.length());
char[] chrs = str.toCharArray();
int sz = chrs.length;
for(int i=0; iAn example is:
*
* - translate("hello", "ho", "jy")
- * => jelly
+ * => jelly
*
*
* If the length of characters to search for is greater than the
@@ -378,24 +351,27 @@
*
*
* CharSetUtils.translate(null, *, *) = null
- * CharSetUtils.translate("", *, *) = ""
+ * CharSetUtils.translate("", *, *) = ""
*
*
* @param str String to replace characters in, may be null
* @param searchChars a set of characters to search for, must not be null
- * @param replaceChars a set of characters to replace, must not be null or empty ("")
+ * @param replaceChars a set of characters to replace, must not be null or empty ("")
* @return translated String, null
if null string input
- * @throws NullPointerException if with
or repl
+ * @throws NullPointerException if searchChars
or replaceChars
* is null
- * @throws ArrayIndexOutOfBoundsException if with
is empty ("")
+ * @throws ArrayIndexOutOfBoundsException if replaceChars
is empty ("")
* @deprecated Use {@link StringUtils#replaceChars(String, String, String)}.
* Method will be removed in Commons Lang 3.0.
+ * NOTE: StringUtils#replaceChars behaves differently when 'searchChars' is longer
+ * than 'replaceChars'. CharSetUtils#translate will use the last char of the replacement
+ * string whereas StringUtils#replaceChars will delete
*/
public static String translate(String str, String searchChars, String replaceChars) {
- if (str == null || str.length() == 0) {
+ if (StringUtils.isEmpty(str)) {
return str;
}
- StringBuffer buffer = new StringBuffer(str.length());
+ StrBuilder buffer = new StrBuilder(str.length());
char[] chrs = str.toCharArray();
char[] withChrs = replaceChars.toCharArray();
int sz = chrs.length;
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/CharUtils.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/CharUtils.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/CharUtils.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,576 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang;
+
+/**
+ * Operations on char primitives and Character objects.
+ *
+ * This class tries to handle null
input gracefully.
+ * An exception will not be thrown for a null
input.
+ * Each method documents its behaviour in more detail.
+ *
+ * #ThreadSafe#
+ * @author Apache Software Foundation
+ * @since 2.1
+ * @version $Id$
+ */
+public class CharUtils {
+
+ private static final String CHAR_STRING =
+ "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007" +
+ "\b\t\n\u000b\f\r\u000e\u000f" +
+ "\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017" +
+ "\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f" +
+ "\u0020\u0021\"\u0023\u0024\u0025\u0026\u0027" +
+ "\u0028\u0029\u002a\u002b\u002c\u002d\u002e\u002f" +
+ "\u0030\u0031\u0032\u0033\u0034\u0035\u0036\u0037" +
+ "\u0038\u0039\u003a\u003b\u003c\u003d\u003e\u003f" +
+ "\u0040\u0041\u0042\u0043\u0044\u0045\u0046\u0047" +
+ "\u0048\u0049\u004a\u004b\u004c\u004d\u004e\u004f" +
+ "\u0050\u0051\u0052\u0053\u0054\u0055\u0056\u0057" +
+ "\u0058\u0059\u005a\u005b\\\u005d\u005e\u005f" +
+ "\u0060\u0061\u0062\u0063\u0064\u0065\u0066\u0067" +
+ "\u0068\u0069\u006a\u006b\u006c\u006d\u006e\u006f" +
+ "\u0070\u0071\u0072\u0073\u0074\u0075\u0076\u0077" +
+ "\u0078\u0079\u007a\u007b\u007c\u007d\u007e\u007f";
+
+ private static final String[] CHAR_STRING_ARRAY = new String[128];
+ private static final Character[] CHAR_ARRAY = new Character[128];
+
+ /**
+ * \u000a
linefeed LF ('\n').
+ *
+ * @see JLF: Escape Sequences
+ * for Character and String Literals
+ * @since 2.2
+ */
+ public static final char LF = '\n';
+
+ /**
+ * \u000d
carriage return CR ('\r').
+ *
+ * @see JLF: Escape Sequences
+ * for Character and String Literals
+ * @since 2.2
+ */
+ public static final char CR = '\r';
+
+
+ static {
+ for (int i = 127; i >= 0; i--) {
+ CHAR_STRING_ARRAY[i] = CHAR_STRING.substring(i, i + 1);
+ CHAR_ARRAY[i] = new Character((char) i);
+ }
+ }
+
+ /**
+ * CharUtils
instances should NOT be constructed in standard programming.
+ * Instead, the class should be used as CharUtils.toString('c');
.
+ *
+ * This constructor is public to permit tools that require a JavaBean instance
+ * to operate.
+ */
+ public CharUtils() {
+ super();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Converts the character to a Character.
+ *
+ * For ASCII 7 bit characters, this uses a cache that will return the
+ * same Character object each time.
+ *
+ *
+ * CharUtils.toCharacterObject(' ') = ' '
+ * CharUtils.toCharacterObject('A') = 'A'
+ *
+ *
+ * @param ch the character to convert
+ * @return a Character of the specified character
+ */
+ public static Character toCharacterObject(char ch) {
+ if (ch < CHAR_ARRAY.length) {
+ return CHAR_ARRAY[ch];
+ }
+ return new Character(ch);
+ }
+
+ /**
+ * Converts the String to a Character using the first character, returning
+ * null for empty Strings.
+ *
+ * For ASCII 7 bit characters, this uses a cache that will return the
+ * same Character object each time.
+ *
+ *
+ * CharUtils.toCharacterObject(null) = null
+ * CharUtils.toCharacterObject("") = null
+ * CharUtils.toCharacterObject("A") = 'A'
+ * CharUtils.toCharacterObject("BA") = 'B'
+ *
+ *
+ * @param str the character to convert
+ * @return the Character value of the first letter of the String
+ */
+ public static Character toCharacterObject(String str) {
+ if (StringUtils.isEmpty(str)) {
+ return null;
+ }
+ return toCharacterObject(str.charAt(0));
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Converts the Character to a char throwing an exception for null
.
+ *
+ *
+ * CharUtils.toChar(null) = IllegalArgumentException
+ * CharUtils.toChar(' ') = ' '
+ * CharUtils.toChar('A') = 'A'
+ *
+ *
+ * @param ch the character to convert
+ * @return the char value of the Character
+ * @throws IllegalArgumentException if the Character is null
+ */
+ public static char toChar(Character ch) {
+ if (ch == null) {
+ throw new IllegalArgumentException("The Character must not be null");
+ }
+ return ch.charValue();
+ }
+
+ /**
+ * Converts the Character to a char handling null
.
+ *
+ *
+ * CharUtils.toChar(null, 'X') = 'X'
+ * CharUtils.toChar(' ', 'X') = ' '
+ * CharUtils.toChar('A', 'X') = 'A'
+ *
+ *
+ * @param ch the character to convert
+ * @param defaultValue the value to use if the Character is null
+ * @return the char value of the Character or the default if null
+ */
+ public static char toChar(Character ch, char defaultValue) {
+ if (ch == null) {
+ return defaultValue;
+ }
+ return ch.charValue();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Converts the String to a char using the first character, throwing
+ * an exception on empty Strings.
+ *
+ *
+ * CharUtils.toChar(null) = IllegalArgumentException
+ * CharUtils.toChar("") = IllegalArgumentException
+ * CharUtils.toChar("A") = 'A'
+ * CharUtils.toChar("BA") = 'B'
+ *
+ *
+ * @param str the character to convert
+ * @return the char value of the first letter of the String
+ * @throws IllegalArgumentException if the String is empty
+ */
+ public static char toChar(String str) {
+ if (StringUtils.isEmpty(str)) {
+ throw new IllegalArgumentException("The String must not be empty");
+ }
+ return str.charAt(0);
+ }
+
+ /**
+ * Converts the String to a char using the first character, defaulting
+ * the value on empty Strings.
+ *
+ *
+ * CharUtils.toChar(null, 'X') = 'X'
+ * CharUtils.toChar("", 'X') = 'X'
+ * CharUtils.toChar("A", 'X') = 'A'
+ * CharUtils.toChar("BA", 'X') = 'B'
+ *
+ *
+ * @param str the character to convert
+ * @param defaultValue the value to use if the Character is null
+ * @return the char value of the first letter of the String or the default if null
+ */
+ public static char toChar(String str, char defaultValue) {
+ if (StringUtils.isEmpty(str)) {
+ return defaultValue;
+ }
+ return str.charAt(0);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Converts the character to the Integer it represents, throwing an
+ * exception if the character is not numeric.
+ *
+ * This method coverts the char '1' to the int 1 and so on.
+ *
+ *
+ * CharUtils.toIntValue('3') = 3
+ * CharUtils.toIntValue('A') = IllegalArgumentException
+ *
+ *
+ * @param ch the character to convert
+ * @return the int value of the character
+ * @throws IllegalArgumentException if the character is not ASCII numeric
+ */
+ public static int toIntValue(char ch) {
+ if (isAsciiNumeric(ch) == false) {
+ throw new IllegalArgumentException("The character " + ch + " is not in the range '0' - '9'");
+ }
+ return ch - 48;
+ }
+
+ /**
+ * Converts the character to the Integer it represents, throwing an
+ * exception if the character is not numeric.
+ *
+ * This method coverts the char '1' to the int 1 and so on.
+ *
+ *
+ * CharUtils.toIntValue('3', -1) = 3
+ * CharUtils.toIntValue('A', -1) = -1
+ *
+ *
+ * @param ch the character to convert
+ * @param defaultValue the default value to use if the character is not numeric
+ * @return the int value of the character
+ */
+ public static int toIntValue(char ch, int defaultValue) {
+ if (isAsciiNumeric(ch) == false) {
+ return defaultValue;
+ }
+ return ch - 48;
+ }
+
+ /**
+ * Converts the character to the Integer it represents, throwing an
+ * exception if the character is not numeric.
+ *
+ * This method coverts the char '1' to the int 1 and so on.
+ *
+ *
+ * CharUtils.toIntValue(null) = IllegalArgumentException
+ * CharUtils.toIntValue('3') = 3
+ * CharUtils.toIntValue('A') = IllegalArgumentException
+ *
+ *
+ * @param ch the character to convert, not null
+ * @return the int value of the character
+ * @throws IllegalArgumentException if the Character is not ASCII numeric or is null
+ */
+ public static int toIntValue(Character ch) {
+ if (ch == null) {
+ throw new IllegalArgumentException("The character must not be null");
+ }
+ return toIntValue(ch.charValue());
+ }
+
+ /**
+ * Converts the character to the Integer it represents, throwing an
+ * exception if the character is not numeric.
+ *
+ * This method coverts the char '1' to the int 1 and so on.
+ *
+ *
+ * CharUtils.toIntValue(null, -1) = -1
+ * CharUtils.toIntValue('3', -1) = 3
+ * CharUtils.toIntValue('A', -1) = -1
+ *
+ *
+ * @param ch the character to convert
+ * @param defaultValue the default value to use if the character is not numeric
+ * @return the int value of the character
+ */
+ public static int toIntValue(Character ch, int defaultValue) {
+ if (ch == null) {
+ return defaultValue;
+ }
+ return toIntValue(ch.charValue(), defaultValue);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Converts the character to a String that contains the one character.
+ *
+ * For ASCII 7 bit characters, this uses a cache that will return the
+ * same String object each time.
+ *
+ *
+ * CharUtils.toString(' ') = " "
+ * CharUtils.toString('A') = "A"
+ *
+ *
+ * @param ch the character to convert
+ * @return a String containing the one specified character
+ */
+ public static String toString(char ch) {
+ if (ch < 128) {
+ return CHAR_STRING_ARRAY[ch];
+ }
+ return new String(new char[] {ch});
+ }
+
+ /**
+ * Converts the character to a String that contains the one character.
+ *
+ * For ASCII 7 bit characters, this uses a cache that will return the
+ * same String object each time.
+ *
+ * If null
is passed in, null
will be returned.
+ *
+ *
+ * CharUtils.toString(null) = null
+ * CharUtils.toString(' ') = " "
+ * CharUtils.toString('A') = "A"
+ *
+ *
+ * @param ch the character to convert
+ * @return a String containing the one specified character
+ */
+ public static String toString(Character ch) {
+ if (ch == null) {
+ return null;
+ }
+ return toString(ch.charValue());
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ * Converts the string to the unicode format '\u0020'.
+ *
+ * This format is the Java source code format.
+ *
+ *
+ * CharUtils.unicodeEscaped(' ') = "\u0020"
+ * CharUtils.unicodeEscaped('A') = "\u0041"
+ *
+ *
+ * @param ch the character to convert
+ * @return the escaped unicode string
+ */
+ public static String unicodeEscaped(char ch) {
+ if (ch < 0x10) {
+ return "\\u000" + Integer.toHexString(ch);
+ } else if (ch < 0x100) {
+ return "\\u00" + Integer.toHexString(ch);
+ } else if (ch < 0x1000) {
+ return "\\u0" + Integer.toHexString(ch);
+ }
+ return "\\u" + Integer.toHexString(ch);
+ }
+
+ /**
+ * Converts the string to the unicode format '\u0020'.
+ *
+ * This format is the Java source code format.
+ *
+ * If null
is passed in, null
will be returned.
+ *
+ *
+ * CharUtils.unicodeEscaped(null) = null
+ * CharUtils.unicodeEscaped(' ') = "\u0020"
+ * CharUtils.unicodeEscaped('A') = "\u0041"
+ *
+ *
+ * @param ch the character to convert, may be null
+ * @return the escaped unicode string, null if null input
+ */
+ public static String unicodeEscaped(Character ch) {
+ if (ch == null) {
+ return null;
+ }
+ return unicodeEscaped(ch.charValue());
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ * Checks whether the character is ASCII 7 bit.
+ *
+ *
+ * CharUtils.isAscii('a') = true
+ * CharUtils.isAscii('A') = true
+ * CharUtils.isAscii('3') = true
+ * CharUtils.isAscii('-') = true
+ * CharUtils.isAscii('\n') = true
+ * CharUtils.isAscii('©') = false
+ *
+ *
+ * @param ch the character to check
+ * @return true if less than 128
+ */
+ public static boolean isAscii(char ch) {
+ return ch < 128;
+ }
+
+ /**
+ * Checks whether the character is ASCII 7 bit printable.
+ *
+ *
+ * CharUtils.isAsciiPrintable('a') = true
+ * CharUtils.isAsciiPrintable('A') = true
+ * CharUtils.isAsciiPrintable('3') = true
+ * CharUtils.isAsciiPrintable('-') = true
+ * CharUtils.isAsciiPrintable('\n') = false
+ * CharUtils.isAsciiPrintable('©') = false
+ *
+ *
+ * @param ch the character to check
+ * @return true if between 32 and 126 inclusive
+ */
+ public static boolean isAsciiPrintable(char ch) {
+ return ch >= 32 && ch < 127;
+ }
+
+ /**
+ * Checks whether the character is ASCII 7 bit control.
+ *
+ *
+ * CharUtils.isAsciiControl('a') = false
+ * CharUtils.isAsciiControl('A') = false
+ * CharUtils.isAsciiControl('3') = false
+ * CharUtils.isAsciiControl('-') = false
+ * CharUtils.isAsciiControl('\n') = true
+ * CharUtils.isAsciiControl('©') = false
+ *
+ *
+ * @param ch the character to check
+ * @return true if less than 32 or equals 127
+ */
+ public static boolean isAsciiControl(char ch) {
+ return ch < 32 || ch == 127;
+ }
+
+ /**
+ * Checks whether the character is ASCII 7 bit alphabetic.
+ *
+ *
+ * CharUtils.isAsciiAlpha('a') = true
+ * CharUtils.isAsciiAlpha('A') = true
+ * CharUtils.isAsciiAlpha('3') = false
+ * CharUtils.isAsciiAlpha('-') = false
+ * CharUtils.isAsciiAlpha('\n') = false
+ * CharUtils.isAsciiAlpha('©') = false
+ *
+ *
+ * @param ch the character to check
+ * @return true if between 65 and 90 or 97 and 122 inclusive
+ */
+ public static boolean isAsciiAlpha(char ch) {
+ return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
+ }
+
+ /**
+ * Checks whether the character is ASCII 7 bit alphabetic upper case.
+ *
+ *
+ * CharUtils.isAsciiAlphaUpper('a') = false
+ * CharUtils.isAsciiAlphaUpper('A') = true
+ * CharUtils.isAsciiAlphaUpper('3') = false
+ * CharUtils.isAsciiAlphaUpper('-') = false
+ * CharUtils.isAsciiAlphaUpper('\n') = false
+ * CharUtils.isAsciiAlphaUpper('©') = false
+ *
+ *
+ * @param ch the character to check
+ * @return true if between 65 and 90 inclusive
+ */
+ public static boolean isAsciiAlphaUpper(char ch) {
+ return ch >= 'A' && ch <= 'Z';
+ }
+
+ /**
+ * Checks whether the character is ASCII 7 bit alphabetic lower case.
+ *
+ *
+ * CharUtils.isAsciiAlphaLower('a') = true
+ * CharUtils.isAsciiAlphaLower('A') = false
+ * CharUtils.isAsciiAlphaLower('3') = false
+ * CharUtils.isAsciiAlphaLower('-') = false
+ * CharUtils.isAsciiAlphaLower('\n') = false
+ * CharUtils.isAsciiAlphaLower('©') = false
+ *
+ *
+ * @param ch the character to check
+ * @return true if between 97 and 122 inclusive
+ */
+ public static boolean isAsciiAlphaLower(char ch) {
+ return ch >= 'a' && ch <= 'z';
+ }
+
+ /**
+ * Checks whether the character is ASCII 7 bit numeric.
+ *
+ *
+ * CharUtils.isAsciiNumeric('a') = false
+ * CharUtils.isAsciiNumeric('A') = false
+ * CharUtils.isAsciiNumeric('3') = true
+ * CharUtils.isAsciiNumeric('-') = false
+ * CharUtils.isAsciiNumeric('\n') = false
+ * CharUtils.isAsciiNumeric('©') = false
+ *
+ *
+ * @param ch the character to check
+ * @return true if between 48 and 57 inclusive
+ */
+ public static boolean isAsciiNumeric(char ch) {
+ return ch >= '0' && ch <= '9';
+ }
+
+ /**
+ * Checks whether the character is ASCII 7 bit numeric.
+ *
+ *
+ * CharUtils.isAsciiAlphanumeric('a') = true
+ * CharUtils.isAsciiAlphanumeric('A') = true
+ * CharUtils.isAsciiAlphanumeric('3') = true
+ * CharUtils.isAsciiAlphanumeric('-') = false
+ * CharUtils.isAsciiAlphanumeric('\n') = false
+ * CharUtils.isAsciiAlphanumeric('©') = false
+ *
+ *
+ * @param ch the character to check
+ * @return true if between 48 and 57 or 65 and 90 or 97 and 122 inclusive
+ */
+ public static boolean isAsciiAlphanumeric(char ch) {
+ return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9');
+ }
+
+ // ----------------- Following code copied from Apache Harmony (Character class)
+ /**
+ * Indicates whether {@code ch} is a high- (or leading-) surrogate code unit
+ * that is used for representing supplementary characters in UTF-16
+ * encoding.
+ *
+ * @param ch
+ * the character to test.
+ * @return {@code true} if {@code ch} is a high-surrogate code unit;
+ * {@code false} otherwise.
+ */
+ static boolean isHighSurrogate(char ch) {
+ return ('\uD800' <= ch && '\uDBFF' >= ch);
+ }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/ClassUtils.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/ClassUtils.java (.../ClassUtils.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/ClassUtils.java (.../ClassUtils.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,95 +1,138 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
*
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+ * 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.
*/
package org.apache.commons.lang;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang.text.StrBuilder;
+
/**
* Operates on classes without using reflection.
*
* This class handles invalid null
inputs as best it can.
* Each method documents its behaviour in more detail.
*
- * @author Stephen Colebourne
+ * The notion of a canonical name
includes the human
+ * readable name for the type, for example int[]
. The
+ * non-canonical method variants work with the JVM names, such as
+ * [I
.
+ *
+ * @author Apache Software Foundation
* @author Gary Gregory
+ * @author Norm Deane
+ * @author Alban Peignier
+ * @author Tomasz Blachowicz
* @since 2.0
* @version $Id$
*/
public class ClassUtils {
/**
- * The package separator character: .
.
+ * The package separator character: '.' == {@value}
.
*/
public static final char PACKAGE_SEPARATOR_CHAR = '.';
-
+
/**
- * The package separator String: .
.
+ * The package separator String: "."
.
*/
public static final String PACKAGE_SEPARATOR = String.valueOf(PACKAGE_SEPARATOR_CHAR);
-
+
/**
- * The inner class separator character: $
.
+ * The inner class separator character: '$' == {@value}
.
*/
public static final char INNER_CLASS_SEPARATOR_CHAR = '$';
-
+
/**
- * The inner class separator String: $
.
+ * The inner class separator String: "$"
.
*/
public static final String INNER_CLASS_SEPARATOR = String.valueOf(INNER_CLASS_SEPARATOR_CHAR);
-
+
/**
+ * Maps primitive Class
es to their corresponding wrapper Class
.
+ */
+ private static final Map primitiveWrapperMap = new HashMap();
+ static {
+ primitiveWrapperMap.put(Boolean.TYPE, Boolean.class);
+ primitiveWrapperMap.put(Byte.TYPE, Byte.class);
+ primitiveWrapperMap.put(Character.TYPE, Character.class);
+ primitiveWrapperMap.put(Short.TYPE, Short.class);
+ primitiveWrapperMap.put(Integer.TYPE, Integer.class);
+ primitiveWrapperMap.put(Long.TYPE, Long.class);
+ primitiveWrapperMap.put(Double.TYPE, Double.class);
+ primitiveWrapperMap.put(Float.TYPE, Float.class);
+ primitiveWrapperMap.put(Void.TYPE, Void.TYPE);
+ }
+
+ /**
+ * Maps wrapper Class
es to their corresponding primitive types.
+ */
+ private static final Map wrapperPrimitiveMap = new HashMap();
+ static {
+ for (Iterator it = primitiveWrapperMap.keySet().iterator(); it.hasNext();) {
+ Class primitiveClass = (Class) it.next();
+ Class wrapperClass = (Class) primitiveWrapperMap.get(primitiveClass);
+ if (!primitiveClass.equals(wrapperClass)) {
+ wrapperPrimitiveMap.put(wrapperClass, primitiveClass);
+ }
+ }
+ }
+
+ /**
+ * Maps a primitive class name to its corresponding abbreviation used in array class names.
+ */
+ private static final Map abbreviationMap = new HashMap();
+
+ /**
+ * Maps an abbreviation used in array class names to corresponding primitive class name.
+ */
+ private static final Map reverseAbbreviationMap = new HashMap();
+
+ /**
+ * Add primitive type abbreviation to maps of abbreviations.
+ *
+ * @param primitive Canonical name of primitive type
+ * @param abbreviation Corresponding abbreviation of primitive type
+ */
+ private static void addAbbreviation(String primitive, String abbreviation) {
+ abbreviationMap.put(primitive, abbreviation);
+ reverseAbbreviationMap.put(abbreviation, primitive);
+ }
+
+ /**
+ * Feed abbreviation maps
+ */
+ static {
+ addAbbreviation("int", "I");
+ addAbbreviation("boolean", "Z");
+ addAbbreviation("float", "F");
+ addAbbreviation("long", "J");
+ addAbbreviation("short", "S");
+ addAbbreviation("byte", "B");
+ addAbbreviation("double", "D");
+ addAbbreviation("char", "C");
+ }
+
+ /**
* ClassUtils instances should NOT be constructed in standard programming.
* Instead, the class should be used as
* ClassUtils.getShortClassName(cls)
.
@@ -98,13 +141,14 @@
* instance to operate.
*/
public ClassUtils() {
+ super();
}
// Short class name
// ----------------------------------------------------------------------
/**
* Gets the class name minus the package name for an Object
.
- *
+ *
* @param object the class to get the short name for, may be null
* @param valueIfNull the value to return if null
* @return the class name of the object without the package name, or the null value
@@ -113,55 +157,71 @@
if (object == null) {
return valueIfNull;
}
- return getShortClassName(object.getClass().getName());
+ return getShortClassName(object.getClass());
}
-
+
/**
* Gets the class name minus the package name from a Class
.
- *
- * @param cls the class to get the short name for, must not be
- * null
- * @return the class name without the package name
- * @throws IllegalArgumentException if the class is null
+ *
+ * @param cls the class to get the short name for.
+ * @return the class name without the package name or an empty string
*/
public static String getShortClassName(Class cls) {
if (cls == null) {
- throw new IllegalArgumentException("The class must not be null");
+ return StringUtils.EMPTY;
}
return getShortClassName(cls.getName());
}
-
+
/**
* Gets the class name minus the package name from a String.
*
* The string passed in is assumed to be a class name - it is not checked.
- *
- * @param className the className to get the short name for,
- * must not be empty or null
- * @return the class name of the class without the package name
- * @throws IllegalArgumentException if the className is empty
+ *
+ * @param className the className to get the short name for
+ * @return the class name of the class without the package name or an empty string
*/
public static String getShortClassName(String className) {
- if (StringUtils.isEmpty(className)) {
- throw new IllegalArgumentException("The class name must not be empty");
+ if (className == null) {
+ return StringUtils.EMPTY;
}
- char[] chars = className.toCharArray();
- int lastDot = 0;
- for (int i = 0; i < chars.length; i++) {
- if (chars[i] == PACKAGE_SEPARATOR_CHAR) {
- lastDot = i + 1;
- } else if (chars[i] == INNER_CLASS_SEPARATOR_CHAR) { // handle inner classes
- chars[i] = PACKAGE_SEPARATOR_CHAR;
+ if (className.length() == 0) {
+ return StringUtils.EMPTY;
+ }
+
+ StrBuilder arrayPrefix = new StrBuilder();
+
+ // Handle array encoding
+ if (className.startsWith("[")) {
+ while (className.charAt(0) == '[') {
+ className = className.substring(1);
+ arrayPrefix.append("[]");
}
+ // Strip Object type encoding
+ if (className.charAt(0) == 'L' && className.charAt(className.length() - 1) == ';') {
+ className = className.substring(1, className.length() - 1);
+ }
}
- return new String(chars, lastDot, chars.length - lastDot);
+
+ if (reverseAbbreviationMap.containsKey(className)) {
+ className = (String)reverseAbbreviationMap.get(className);
+ }
+
+ int lastDotIdx = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
+ int innerIdx = className.indexOf(
+ INNER_CLASS_SEPARATOR_CHAR, lastDotIdx == -1 ? 0 : lastDotIdx + 1);
+ String out = className.substring(lastDotIdx + 1);
+ if (innerIdx != -1) {
+ out = out.replace(INNER_CLASS_SEPARATOR_CHAR, PACKAGE_SEPARATOR_CHAR);
+ }
+ return out + arrayPrefix;
}
-
+
// Package name
// ----------------------------------------------------------------------
/**
* Gets the package name of an Object
.
- *
+ *
* @param object the class to get the package name for, may be null
* @param valueIfNull the value to return if null
* @return the package name of the object, or the null value
@@ -170,51 +230,58 @@
if (object == null) {
return valueIfNull;
}
- return getPackageName(object.getClass().getName());
+ return getPackageName(object.getClass());
}
-
+
/**
* Gets the package name of a Class
.
- *
- * @param cls the class to get the package name for,
- * must not be null
- * @return the package name
- * @throws IllegalArgumentException if the class is null
+ *
+ * @param cls the class to get the package name for, may be null
.
+ * @return the package name or an empty string
*/
public static String getPackageName(Class cls) {
if (cls == null) {
- throw new IllegalArgumentException("The class must not be null");
+ return StringUtils.EMPTY;
}
return getPackageName(cls.getName());
}
-
+
/**
* Gets the package name from a String
.
*
* The string passed in is assumed to be a class name - it is not checked.
- *
- * @param className the className to get the package name for,
- * must not be empty or null
- * @return the package name
- * @throws IllegalArgumentException if the className is empty
+ * If the class is unpackaged, return an empty string.
+ *
+ * @param className the className to get the package name for, may be null
+ * @return the package name or an empty string
*/
public static String getPackageName(String className) {
- if (StringUtils.isEmpty(className)) {
- throw new IllegalArgumentException("The class name must not be empty");
+ if (className == null || className.length() == 0) {
+ return StringUtils.EMPTY;
}
+
+ // Strip array encoding
+ while (className.charAt(0) == '[') {
+ className = className.substring(1);
+ }
+ // Strip Object type encoding
+ if (className.charAt(0) == 'L' && className.charAt(className.length() - 1) == ';') {
+ className = className.substring(1);
+ }
+
int i = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
if (i == -1) {
- return "";
+ return StringUtils.EMPTY;
}
return className.substring(0, i);
}
-
+
// Superclasses/Superinterfaces
// ----------------------------------------------------------------------
/**
* Gets a List
of superclasses for the given class.
- *
- * @param cls the class to look up, must not be null
+ *
+ * @param cls the class to look up, may be null
* @return the List
of superclasses in order going up from this one
* null
if null input
*/
@@ -230,97 +297,52 @@
}
return classes;
}
-
+
/**
* Gets a List
of all interfaces implemented by the given
* class and its superclasses.
*
* The order is determined by looking through each interface in turn as
- * declared in the source file and following its hieracrchy up. Then each
- * superclass is considered in the same way. Later duplicates are ignored,
+ * declared in the source file and following its hierarchy up. Then each
+ * superclass is considered in the same way. Later duplicates are ignored,
* so the order is maintained.
- *
- * @param cls the class to look up, must not be null
+ *
+ * @param cls the class to look up, may be null
* @return the List
of interfaces in order,
* null
if null input
*/
public static List getAllInterfaces(Class cls) {
if (cls == null) {
return null;
}
- List list = new ArrayList();
+
+ List interfacesFound = new ArrayList();
+ getAllInterfaces(cls, interfacesFound);
+
+ return interfacesFound;
+ }
+
+ /**
+ * Get the interfaces for the specified class.
+ *
+ * @param cls the class to look up, may be null
+ * @param interfacesFound the Set
of interfaces for the class
+ */
+ private static void getAllInterfaces(Class cls, List interfacesFound) {
while (cls != null) {
Class[] interfaces = cls.getInterfaces();
+
for (int i = 0; i < interfaces.length; i++) {
- if (list.contains(interfaces[i]) == false) {
- list.add(interfaces[i]);
+ if (!interfacesFound.contains(interfaces[i])) {
+ interfacesFound.add(interfaces[i]);
+ getAllInterfaces(interfaces[i], interfacesFound);
}
- List superInterfaces = getAllInterfaces(interfaces[i]);
- for (Iterator it = superInterfaces.iterator(); it.hasNext();) {
- Class intface = (Class) it.next();
- if (list.contains(intface) == false) {
- list.add(intface);
- }
- }
}
+
cls = cls.getSuperclass();
- }
- return list;
- }
-
-// /**
-// * Gets a List
of subclasses of the specified class.
-// *
-// * This method searches the classpath to find all the subclasses
-// * of a particular class available. No classes are loaded, the
-// * returned list contains class names, not classes.
-// *
-// * @param cls the class to find subclasses for
-// * @return the List
of subclass String class names
-// * @throws IllegalArgumentException if the class is null
-// */
-// public static List getAllSubclassNames(Class cls) {
-// if (cls == null) {
-// throw new IllegalArgumentException("The class must not be null");
-// }
-// // TODO Use JavaWorld tip for searching the classpath
-// return null;
-// }
+ }
+ }
-// /**
-// * Gets a List
of subclasses of the specified class.
-// *
-// * This method searches the classpath to find all the subclasses
-// * of a particular class available.
-// *
-// * @param cls the class to find subclasses for
-// * @return the List
of subclasses
-// * @throws IllegalArgumentException if the class is null
-// */
-// public static List getAllSubclasses(Class cls) {
-// List names = getAllSubclassNames(cls);
-// return convertClassNamesToClasses(names);
-// }
-
-// /**
-// * Gets a List
of implementations of the specified interface.
-// *
-// * This method searches the classpath to find all the implementations
-// * of a particular interface available. No classes are loaded, the
-// * returned list contains class names, not classes.
-// *
-// * @param cls the class to find sub classes for
-// * @return the List
of implementation String class names
-// * @throws IllegalArgumentException if the class is null
-// */
-// public static List getAllImplementationClassNames(Class cls) {
-// if (cls == null) {
-// throw new IllegalArgumentException("The class must not be null");
-// }
-// // TODO Use JavaWorld tip for searching the classpath
-// return null;
-// }
-
// Convert list
// ----------------------------------------------------------------------
/**
@@ -329,7 +351,7 @@
* A new List
is returned. If the class name cannot be found, null
* is stored in the List
. If the class name in the List
is
* null
, null
is stored in the output List
.
- *
+ *
* @param classNames the classNames to change
* @return a List
of Class objects corresponding to the class names,
* null
if null input
@@ -350,18 +372,18 @@
}
return classes;
}
-
+
/**
* Given a List
of Class
objects, this method converts
* them into class names.
*
* A new List
is returned. null
objects will be copied into
* the returned list as null
.
- *
+ *
* @param classes the classes to change
- * @return a List
of Class objects corresponding to the class names,
+ * @return a List
of class names corresponding to the Class objects,
* null
if null input
- * @throws ClassCastException if classNames contains a non Class or null entry
+ * @throws ClassCastException if classes
contains a non-Class
entry
*/
public static List convertClassesToClassNames(List classes) {
if (classes == null) {
@@ -378,15 +400,15 @@
}
return classNames;
}
-
+
// Is assignable
// ----------------------------------------------------------------------
/**
* Checks if an array of Classes can be assigned to another array of Classes.
*
* This method calls {@link #isAssignable(Class, Class) isAssignable} for each
* Class pair in the input arrays. It can be used to check if a set of arguments
- * (the first parameter) are suitably compatable with a set of method parameter types
+ * (the first parameter) are suitably compatible with a set of method parameter types
* (the second parameter).
*
* Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method, this
@@ -404,7 +426,7 @@
*
Specifically, this method tests whether the type represented by the
* specified Class
parameter can be converted to the type
* represented by this Class
object via an identity conversion
- * widening primitive or widening reference conversion. See
+ * widening primitive or widening reference conversion. See
* The Java Language Specification,
* sections 5.1.1, 5.1.2 and 5.1.4 for details.
*
@@ -413,6 +435,43 @@
* @return true
if assignment possible
*/
public static boolean isAssignable(Class[] classArray, Class[] toClassArray) {
+ return isAssignable(classArray, toClassArray, false);
+ }
+
+ /**
+ * Checks if an array of Classes can be assigned to another array of Classes.
+ *
+ * This method calls {@link #isAssignable(Class, Class) isAssignable} for each
+ * Class pair in the input arrays. It can be used to check if a set of arguments
+ * (the first parameter) are suitably compatible with a set of method parameter types
+ * (the second parameter).
+ *
+ * Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method, this
+ * method takes into account widenings of primitive classes and
+ * null
s.
+ *
+ * Primitive widenings allow an int to be assigned to a long
,
+ * float
or double
. This method returns the correct
+ * result for these cases.
+ *
+ * Null
may be assigned to any reference type. This method will
+ * return true
if null
is passed in and the toClass is
+ * non-primitive.
+ *
+ * Specifically, this method tests whether the type represented by the
+ * specified Class
parameter can be converted to the type
+ * represented by this Class
object via an identity conversion
+ * widening primitive or widening reference conversion. See
+ * The Java Language Specification,
+ * sections 5.1.1, 5.1.2 and 5.1.4 for details.
+ *
+ * @param classArray the array of Classes to check, may be null
+ * @param toClassArray the array of Classes to try to assign into, may be null
+ * @param autoboxing whether to use implicit autoboxing/unboxing between primitives and wrappers
+ * @return true
if assignment possible
+ * @since 2.5
+ */
+ public static boolean isAssignable(Class[] classArray, Class[] toClassArray, boolean autoboxing) {
if (ArrayUtils.isSameLength(classArray, toClassArray) == false) {
return false;
}
@@ -423,13 +482,13 @@
toClassArray = ArrayUtils.EMPTY_CLASS_ARRAY;
}
for (int i = 0; i < classArray.length; i++) {
- if (isAssignable(classArray[i], toClassArray[i]) == false) {
+ if (isAssignable(classArray[i], toClassArray[i], autoboxing) == false) {
return false;
}
}
return true;
}
-
+
/**
* Checks if one Class
can be assigned to a variable of
* another Class
.
@@ -448,7 +507,7 @@
* Specifically, this method tests whether the type represented by the
* specified Class
parameter can be converted to the type
* represented by this Class
object via an identity conversion
- * widening primitive or widening reference conversion. See
+ * widening primitive or widening reference conversion. See
* The Java Language Specification,
* sections 5.1.1, 5.1.2 and 5.1.4 for details.
*
@@ -457,13 +516,60 @@
* @return true
if assignment possible
*/
public static boolean isAssignable(Class cls, Class toClass) {
+ return isAssignable(cls, toClass, false);
+ }
+
+ /**
+ * Checks if one Class
can be assigned to a variable of
+ * another Class
.
+ *
+ * Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method,
+ * this method takes into account widenings of primitive classes and
+ * null
s.
+ *
+ * Primitive widenings allow an int to be assigned to a long, float or
+ * double. This method returns the correct result for these cases.
+ *
+ * Null
may be assigned to any reference type. This method
+ * will return true
if null
is passed in and the
+ * toClass is non-primitive.
+ *
+ * Specifically, this method tests whether the type represented by the
+ * specified Class
parameter can be converted to the type
+ * represented by this Class
object via an identity conversion
+ * widening primitive or widening reference conversion. See
+ * The Java Language Specification,
+ * sections 5.1.1, 5.1.2 and 5.1.4 for details.
+ *
+ * @param cls the Class to check, may be null
+ * @param toClass the Class to try to assign into, returns false if null
+ * @param autoboxing whether to use implicit autoboxing/unboxing between primitives and wrappers
+ * @return true
if assignment possible
+ * @since 2.5
+ */
+ public static boolean isAssignable(Class cls, Class toClass, boolean autoboxing) {
if (toClass == null) {
return false;
}
// have to check for null, as isAssignableFrom doesn't
if (cls == null) {
return !(toClass.isPrimitive());
}
+ //autoboxing:
+ if (autoboxing) {
+ if (cls.isPrimitive() && !toClass.isPrimitive()) {
+ cls = primitiveToWrapper(cls);
+ if (cls == null) {
+ return false;
+ }
+ }
+ if (toClass.isPrimitive() && !cls.isPrimitive()) {
+ cls = wrapperToPrimitive(cls);
+ if (cls == null) {
+ return false;
+ }
+ }
+ }
if (cls.equals(toClass)) {
return true;
}
@@ -472,12 +578,12 @@
return false;
}
if (Integer.TYPE.equals(cls)) {
- return Long.TYPE.equals(toClass)
- || Float.TYPE.equals(toClass)
+ return Long.TYPE.equals(toClass)
+ || Float.TYPE.equals(toClass)
|| Double.TYPE.equals(toClass);
}
if (Long.TYPE.equals(cls)) {
- return Float.TYPE.equals(toClass)
+ return Float.TYPE.equals(toClass)
|| Double.TYPE.equals(toClass);
}
if (Boolean.TYPE.equals(cls)) {
@@ -490,44 +596,474 @@
return Double.TYPE.equals(toClass);
}
if (Character.TYPE.equals(cls)) {
- return Integer.TYPE.equals(toClass)
- || Long.TYPE.equals(toClass)
- || Float.TYPE.equals(toClass)
+ return Integer.TYPE.equals(toClass)
+ || Long.TYPE.equals(toClass)
+ || Float.TYPE.equals(toClass)
|| Double.TYPE.equals(toClass);
}
if (Short.TYPE.equals(cls)) {
- return Integer.TYPE.equals(toClass)
- || Long.TYPE.equals(toClass)
- || Float.TYPE.equals(toClass)
+ return Integer.TYPE.equals(toClass)
+ || Long.TYPE.equals(toClass)
+ || Float.TYPE.equals(toClass)
|| Double.TYPE.equals(toClass);
}
if (Byte.TYPE.equals(cls)) {
- return Short.TYPE.equals(toClass)
- || Integer.TYPE.equals(toClass)
- || Long.TYPE.equals(toClass)
- || Float.TYPE.equals(toClass)
+ return Short.TYPE.equals(toClass)
+ || Integer.TYPE.equals(toClass)
+ || Long.TYPE.equals(toClass)
+ || Float.TYPE.equals(toClass)
|| Double.TYPE.equals(toClass);
}
// should never get here
return false;
}
return toClass.isAssignableFrom(cls);
}
-
+
+ /**
+ * Converts the specified primitive Class object to its corresponding
+ * wrapper Class object.
+ *
+ * NOTE: From v2.2, this method handles Void.TYPE
,
+ * returning Void.TYPE
.
+ *
+ * @param cls the class to convert, may be null
+ * @return the wrapper class for cls
or cls
if
+ * cls
is not a primitive. null
if null input.
+ * @since 2.1
+ */
+ public static Class primitiveToWrapper(Class cls) {
+ Class convertedClass = cls;
+ if (cls != null && cls.isPrimitive()) {
+ convertedClass = (Class) primitiveWrapperMap.get(cls);
+ }
+ return convertedClass;
+ }
+
+ /**
+ * Converts the specified array of primitive Class objects to an array of
+ * its corresponding wrapper Class objects.
+ *
+ * @param classes the class array to convert, may be null or empty
+ * @return an array which contains for each given class, the wrapper class or
+ * the original class if class is not a primitive. null
if null input.
+ * Empty array if an empty array passed in.
+ * @since 2.1
+ */
+ public static Class[] primitivesToWrappers(Class[] classes) {
+ if (classes == null) {
+ return null;
+ }
+
+ if (classes.length == 0) {
+ return classes;
+ }
+
+ Class[] convertedClasses = new Class[classes.length];
+ for (int i = 0; i < classes.length; i++) {
+ convertedClasses[i] = primitiveToWrapper(classes[i]);
+ }
+ return convertedClasses;
+ }
+
+ /**
+ * Converts the specified wrapper class to its corresponding primitive
+ * class.
+ *
+ * This method is the counter part of primitiveToWrapper()
.
+ * If the passed in class is a wrapper class for a primitive type, this
+ * primitive type will be returned (e.g. Integer.TYPE
for
+ * Integer.class
). For other classes, or if the parameter is
+ * null, the return value is null.
+ *
+ * @param cls the class to convert, may be null
+ * @return the corresponding primitive type if cls
is a
+ * wrapper class, null otherwise
+ * @see #primitiveToWrapper(Class)
+ * @since 2.4
+ */
+ public static Class wrapperToPrimitive(Class cls) {
+ return (Class) wrapperPrimitiveMap.get(cls);
+ }
+
+ /**
+ * Converts the specified array of wrapper Class objects to an array of
+ * its corresponding primitive Class objects.
+ *
+ * This method invokes wrapperToPrimitive()
for each element
+ * of the passed in array.
+ *
+ * @param classes the class array to convert, may be null or empty
+ * @return an array which contains for each given class, the primitive class or
+ * null if the original class is not a wrapper class. null
if null input.
+ * Empty array if an empty array passed in.
+ * @see #wrapperToPrimitive(Class)
+ * @since 2.4
+ */
+ public static Class[] wrappersToPrimitives(Class[] classes) {
+ if (classes == null) {
+ return null;
+ }
+
+ if (classes.length == 0) {
+ return classes;
+ }
+
+ Class[] convertedClasses = new Class[classes.length];
+ for (int i = 0; i < classes.length; i++) {
+ convertedClasses[i] = wrapperToPrimitive(classes[i]);
+ }
+ return convertedClasses;
+ }
+
// Inner class
// ----------------------------------------------------------------------
/**
* Is the specified class an inner class or static nested class.
- *
- * @param cls the class to check
+ *
+ * @param cls the class to check, may be null
* @return true
if the class is an inner or static nested class,
* false if not or null
*/
public static boolean isInnerClass(Class cls) {
if (cls == null) {
return false;
}
- return (cls.getName().indexOf(INNER_CLASS_SEPARATOR_CHAR) >= 0);
+ return cls.getName().indexOf(INNER_CLASS_SEPARATOR_CHAR) >= 0;
}
-
+
+ // Class loading
+ // ----------------------------------------------------------------------
+ /**
+ * Returns the class represented by className
using the
+ * classLoader
. This implementation supports the syntaxes
+ * "java.util.Map.Entry[]
", "java.util.Map$Entry[]
",
+ * "[Ljava.util.Map.Entry;
", and "[Ljava.util.Map$Entry;
".
+ *
+ * @param classLoader the class loader to use to load the class
+ * @param className the class name
+ * @param initialize whether the class must be initialized
+ * @return the class represented by className
using the classLoader
+ * @throws ClassNotFoundException if the class is not found
+ */
+ public static Class getClass(
+ ClassLoader classLoader, String className, boolean initialize) throws ClassNotFoundException {
+ try {
+ Class clazz;
+ if (abbreviationMap.containsKey(className)) {
+ String clsName = "[" + abbreviationMap.get(className);
+ clazz = Class.forName(clsName, initialize, classLoader).getComponentType();
+ } else {
+ clazz = Class.forName(toCanonicalName(className), initialize, classLoader);
+ }
+ return clazz;
+ } catch (ClassNotFoundException ex) {
+ // allow path separators (.) as inner class name separators
+ int lastDotIndex = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
+
+ if (lastDotIndex != -1) {
+ try {
+ return getClass(classLoader, className.substring(0, lastDotIndex) +
+ INNER_CLASS_SEPARATOR_CHAR + className.substring(lastDotIndex + 1),
+ initialize);
+ } catch (ClassNotFoundException ex2) {
+ }
+ }
+
+ throw ex;
+ }
+ }
+
+ /**
+ * Returns the (initialized) class represented by className
+ * using the classLoader
. This implementation supports
+ * the syntaxes "java.util.Map.Entry[]
",
+ * "java.util.Map$Entry[]
", "[Ljava.util.Map.Entry;
",
+ * and "[Ljava.util.Map$Entry;
".
+ *
+ * @param classLoader the class loader to use to load the class
+ * @param className the class name
+ * @return the class represented by className
using the classLoader
+ * @throws ClassNotFoundException if the class is not found
+ */
+ public static Class getClass(ClassLoader classLoader, String className) throws ClassNotFoundException {
+ return getClass(classLoader, className, true);
+ }
+
+ /**
+ * Returns the (initialized) class represented by className
+ * using the current thread's context class loader. This implementation
+ * supports the syntaxes "java.util.Map.Entry[]
",
+ * "java.util.Map$Entry[]
", "[Ljava.util.Map.Entry;
",
+ * and "[Ljava.util.Map$Entry;
".
+ *
+ * @param className the class name
+ * @return the class represented by className
using the current thread's context class loader
+ * @throws ClassNotFoundException if the class is not found
+ */
+ public static Class getClass(String className) throws ClassNotFoundException {
+ return getClass(className, true);
+ }
+
+ /**
+ * Returns the class represented by className
using the
+ * current thread's context class loader. This implementation supports the
+ * syntaxes "java.util.Map.Entry[]
", "java.util.Map$Entry[]
",
+ * "[Ljava.util.Map.Entry;
", and "[Ljava.util.Map$Entry;
".
+ *
+ * @param className the class name
+ * @param initialize whether the class must be initialized
+ * @return the class represented by className
using the current thread's context class loader
+ * @throws ClassNotFoundException if the class is not found
+ */
+ public static Class getClass(String className, boolean initialize) throws ClassNotFoundException {
+ ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
+ ClassLoader loader = contextCL == null ? ClassUtils.class.getClassLoader() : contextCL;
+ return getClass(loader, className, initialize );
+ }
+
+ // Public method
+ // ----------------------------------------------------------------------
+ /**
+ * Returns the desired Method much like Class.getMethod
, however
+ * it ensures that the returned Method is from a public class or interface and not
+ * from an anonymous inner class. This means that the Method is invokable and
+ * doesn't fall foul of Java bug
+ * 4071957).
+ *
+ * Set set = Collections.unmodifiableSet(...);
+ * Method method = ClassUtils.getPublicMethod(set.getClass(), "isEmpty", new Class[0]);
+ * Object result = method.invoke(set, new Object[]);
+ *
+ *
+ * @param cls the class to check, not null
+ * @param methodName the name of the method
+ * @param parameterTypes the list of parameters
+ * @return the method
+ * @throws NullPointerException if the class is null
+ * @throws SecurityException if a a security violation occured
+ * @throws NoSuchMethodException if the method is not found in the given class
+ * or if the metothod doen't conform with the requirements
+ */
+ public static Method getPublicMethod(Class cls, String methodName, Class parameterTypes[])
+ throws SecurityException, NoSuchMethodException {
+
+ Method declaredMethod = cls.getMethod(methodName, parameterTypes);
+ if (Modifier.isPublic(declaredMethod.getDeclaringClass().getModifiers())) {
+ return declaredMethod;
+ }
+
+ List candidateClasses = new ArrayList();
+ candidateClasses.addAll(getAllInterfaces(cls));
+ candidateClasses.addAll(getAllSuperclasses(cls));
+
+ for (Iterator it = candidateClasses.iterator(); it.hasNext(); ) {
+ Class candidateClass = (Class) it.next();
+ if (!Modifier.isPublic(candidateClass.getModifiers())) {
+ continue;
+ }
+ Method candidateMethod;
+ try {
+ candidateMethod = candidateClass.getMethod(methodName, parameterTypes);
+ } catch (NoSuchMethodException ex) {
+ continue;
+ }
+ if (Modifier.isPublic(candidateMethod.getDeclaringClass().getModifiers())) {
+ return candidateMethod;
+ }
+ }
+
+ throw new NoSuchMethodException("Can't find a public method for " +
+ methodName + " " + ArrayUtils.toString(parameterTypes));
+ }
+
+ // ----------------------------------------------------------------------
+ /**
+ * Converts a class name to a JLS style class name.
+ *
+ * @param className the class name
+ * @return the converted name
+ */
+ private static String toCanonicalName(String className) {
+ className = StringUtils.deleteWhitespace(className);
+ if (className == null) {
+ throw new NullArgumentException("className");
+ } else if (className.endsWith("[]")) {
+ StrBuilder classNameBuffer = new StrBuilder();
+ while (className.endsWith("[]")) {
+ className = className.substring(0, className.length() - 2);
+ classNameBuffer.append("[");
+ }
+ String abbreviation = (String) abbreviationMap.get(className);
+ if (abbreviation != null) {
+ classNameBuffer.append(abbreviation);
+ } else {
+ classNameBuffer.append("L").append(className).append(";");
+ }
+ className = classNameBuffer.toString();
+ }
+ return className;
+ }
+
+ /**
+ * Converts an array of Object
in to an array of Class
objects.
+ * If any of these objects is null, a null element will be inserted into the array.
+ *
+ * This method returns null
for a null
input array.
+ *
+ * @param array an Object
array
+ * @return a Class
array, null
if null array input
+ * @since 2.4
+ */
+ public static Class[] toClass(Object[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return ArrayUtils.EMPTY_CLASS_ARRAY;
+ }
+ Class[] classes = new Class[array.length];
+ for (int i = 0; i < array.length; i++) {
+ classes[i] = array[i] == null ? null : array[i].getClass();
+ }
+ return classes;
+ }
+
+ // Short canonical name
+ // ----------------------------------------------------------------------
+ /**
+ * Gets the canonical name minus the package name for an Object
.
+ *
+ * @param object the class to get the short name for, may be null
+ * @param valueIfNull the value to return if null
+ * @return the canonical name of the object without the package name, or the null value
+ * @since 2.4
+ */
+ public static String getShortCanonicalName(Object object, String valueIfNull) {
+ if (object == null) {
+ return valueIfNull;
+ }
+ return getShortCanonicalName(object.getClass().getName());
+ }
+
+ /**
+ * Gets the canonical name minus the package name from a Class
.
+ *
+ * @param cls the class to get the short name for.
+ * @return the canonical name without the package name or an empty string
+ * @since 2.4
+ */
+ public static String getShortCanonicalName(Class cls) {
+ if (cls == null) {
+ return StringUtils.EMPTY;
+ }
+ return getShortCanonicalName(cls.getName());
+ }
+
+ /**
+ * Gets the canonical name minus the package name from a String.
+ *
+ * The string passed in is assumed to be a canonical name - it is not checked.
+ *
+ * @param canonicalName the class name to get the short name for
+ * @return the canonical name of the class without the package name or an empty string
+ * @since 2.4
+ */
+ public static String getShortCanonicalName(String canonicalName) {
+ return ClassUtils.getShortClassName(getCanonicalName(canonicalName));
+ }
+
+ // Package name
+ // ----------------------------------------------------------------------
+ /**
+ * Gets the package name from the canonical name of an Object
.
+ *
+ * @param object the class to get the package name for, may be null
+ * @param valueIfNull the value to return if null
+ * @return the package name of the object, or the null value
+ * @since 2.4
+ */
+ public static String getPackageCanonicalName(Object object, String valueIfNull) {
+ if (object == null) {
+ return valueIfNull;
+ }
+ return getPackageCanonicalName(object.getClass().getName());
+ }
+
+ /**
+ * Gets the package name from the canonical name of a Class
.
+ *
+ * @param cls the class to get the package name for, may be null
.
+ * @return the package name or an empty string
+ * @since 2.4
+ */
+ public static String getPackageCanonicalName(Class cls) {
+ if (cls == null) {
+ return StringUtils.EMPTY;
+ }
+ return getPackageCanonicalName(cls.getName());
+ }
+
+ /**
+ * Gets the package name from the canonical name.
+ *
+ * The string passed in is assumed to be a canonical name - it is not checked.
+ * If the class is unpackaged, return an empty string.
+ *
+ * @param canonicalName the canonical name to get the package name for, may be null
+ * @return the package name or an empty string
+ * @since 2.4
+ */
+ public static String getPackageCanonicalName(String canonicalName) {
+ return ClassUtils.getPackageName(getCanonicalName(canonicalName));
+ }
+
+ /**
+ * Converts a given name of class into canonical format.
+ * If name of class is not a name of array class it returns
+ * unchanged name.
+ * Example:
+ *
+ * getCanonicalName("[I") = "int[]"
+ * getCanonicalName("[Ljava.lang.String;") = "java.lang.String[]"
+ * getCanonicalName("java.lang.String") = "java.lang.String"
+ *
+ *
+ *
+ * @param className the name of class
+ * @return canonical form of class name
+ * @since 2.4
+ */
+ private static String getCanonicalName(String className) {
+ className = StringUtils.deleteWhitespace(className);
+ if (className == null) {
+ return null;
+ } else {
+ int dim = 0;
+ while (className.startsWith("[")) {
+ dim++;
+ className = className.substring(1);
+ }
+ if (dim < 1) {
+ return className;
+ } else {
+ if (className.startsWith("L")) {
+ className = className.substring(
+ 1,
+ className.endsWith(";")
+ ? className.length() - 1
+ : className.length());
+ } else {
+ if (className.length() > 0) {
+ className = (String) reverseAbbreviationMap.get(
+ className.substring(0, 1));
+ }
+ }
+ StrBuilder canonicalClassNameBuffer = new StrBuilder(className);
+ for (int i = 0; i < dim; i++) {
+ canonicalClassNameBuffer.append("[]");
+ }
+ return canonicalClassNameBuffer.toString();
+ }
+ }
+ }
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/Entities.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/Entities.java (.../Entities.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/Entities.java (.../Entities.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,123 +1,89 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
+
package org.apache.commons.lang;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
/**
- * Provides HTML and XML entity utilities.
- *
+ *
+ * Provides HTML and XML entity utilities.
+ *
+ *
* @see ISO Entities
- * @see HTML 3.2 Character Entities for ISO Latin-1
- * @see HTML 4.0 Character entity references
- * @see HTML 4.01 Character References
- * @see HTML 4.01 Code positions
- *
+ * @see HTML 3.2 Character Entities for ISO Latin-1
+ * @see HTML 4.0 Character entity references
+ * @see HTML 4.01 Character References
+ * @see HTML 4.01 Code positions
+ *
* @author Alexander Day Chaffee
* @author Gary Gregory
* @since 2.0
* @version $Id$
*/
class Entities {
- private static final String[][] BASIC_ARRAY = {
- {"quot", "34"}, // " - double-quote
+ private static final String[][] BASIC_ARRAY = {{"quot", "34"}, // " - double-quote
{"amp", "38"}, // & - ampersand
{"lt", "60"}, // < - less-than
{"gt", "62"}, // > - greater-than
};
- private static final String[][] APOS_ARRAY = {
- {"apos", "39"}, // XML apostrophe
+ private static final String[][] APOS_ARRAY = {{"apos", "39"}, // XML apostrophe
};
// package scoped for testing
- static final String[][] ISO8859_1_ARRAY = {
- {"nbsp", "160"}, // non-breaking space
- {"iexcl", "161"}, //inverted exclamation mark
- {"cent", "162"}, //cent sign
- {"pound", "163"}, //pound sign
- {"curren", "164"}, //currency sign
- {"yen", "165"}, //yen sign = yuan sign
- {"brvbar", "166"}, //broken bar = broken vertical bar
- {"sect", "167"}, //section sign
- {"uml", "168"}, //diaeresis = spacing diaeresis
+ static final String[][] ISO8859_1_ARRAY = {{"nbsp", "160"}, // non-breaking space
+ {"iexcl", "161"}, // inverted exclamation mark
+ {"cent", "162"}, // cent sign
+ {"pound", "163"}, // pound sign
+ {"curren", "164"}, // currency sign
+ {"yen", "165"}, // yen sign = yuan sign
+ {"brvbar", "166"}, // broken bar = broken vertical bar
+ {"sect", "167"}, // section sign
+ {"uml", "168"}, // diaeresis = spacing diaeresis
{"copy", "169"}, // � - copyright sign
- {"ordf", "170"}, //feminine ordinal indicator
- {"laquo", "171"}, //left-pointing double angle quotation mark = left pointing guillemet
- {"not", "172"}, //not sign
- {"shy", "173"}, //soft hyphen = discretionary hyphen
+ {"ordf", "170"}, // feminine ordinal indicator
+ {"laquo", "171"}, // left-pointing double angle quotation mark = left pointing guillemet
+ {"not", "172"}, // not sign
+ {"shy", "173"}, // soft hyphen = discretionary hyphen
{"reg", "174"}, // � - registered trademark sign
- {"macr", "175"}, //macron = spacing macron = overline = APL overbar
- {"deg", "176"}, //degree sign
- {"plusmn", "177"}, //plus-minus sign = plus-or-minus sign
- {"sup2", "178"}, //superscript two = superscript digit two = squared
- {"sup3", "179"}, //superscript three = superscript digit three = cubed
- {"acute", "180"}, //acute accent = spacing acute
- {"micro", "181"}, //micro sign
- {"para", "182"}, //pilcrow sign = paragraph sign
- {"middot", "183"}, //middle dot = Georgian comma = Greek middle dot
- {"cedil", "184"}, //cedilla = spacing cedilla
- {"sup1", "185"}, //superscript one = superscript digit one
- {"ordm", "186"}, //masculine ordinal indicator
- {"raquo", "187"}, //right-pointing double angle quotation mark = right pointing guillemet
- {"frac14", "188"}, //vulgar fraction one quarter = fraction one quarter
- {"frac12", "189"}, //vulgar fraction one half = fraction one half
- {"frac34", "190"}, //vulgar fraction three quarters = fraction three quarters
- {"iquest", "191"}, //inverted question mark = turned question mark
+ {"macr", "175"}, // macron = spacing macron = overline = APL overbar
+ {"deg", "176"}, // degree sign
+ {"plusmn", "177"}, // plus-minus sign = plus-or-minus sign
+ {"sup2", "178"}, // superscript two = superscript digit two = squared
+ {"sup3", "179"}, // superscript three = superscript digit three = cubed
+ {"acute", "180"}, // acute accent = spacing acute
+ {"micro", "181"}, // micro sign
+ {"para", "182"}, // pilcrow sign = paragraph sign
+ {"middot", "183"}, // middle dot = Georgian comma = Greek middle dot
+ {"cedil", "184"}, // cedilla = spacing cedilla
+ {"sup1", "185"}, // superscript one = superscript digit one
+ {"ordm", "186"}, // masculine ordinal indicator
+ {"raquo", "187"}, // right-pointing double angle quotation mark = right pointing guillemet
+ {"frac14", "188"}, // vulgar fraction one quarter = fraction one quarter
+ {"frac12", "189"}, // vulgar fraction one half = fraction one half
+ {"frac34", "190"}, // vulgar fraction three quarters = fraction three quarters
+ {"iquest", "191"}, // inverted question mark = turned question mark
{"Agrave", "192"}, // � - uppercase A, grave accent
{"Aacute", "193"}, // � - uppercase A, acute accent
{"Acirc", "194"}, // � - uppercase A, circumflex accent
@@ -141,7 +107,7 @@
{"Ocirc", "212"}, // � - uppercase O, circumflex accent
{"Otilde", "213"}, // � - uppercase O, tilde
{"Ouml", "214"}, // � - uppercase O, umlaut
- {"times", "215"}, //multiplication sign
+ {"times", "215"}, // multiplication sign
{"Oslash", "216"}, // � - uppercase O, slash
{"Ugrave", "217"}, // � - uppercase U, grave accent
{"Uacute", "218"}, // � - uppercase U, acute accent
@@ -187,310 +153,422 @@
// http://www.w3.org/TR/REC-html40/sgml/entities.html
// package scoped for testing
static final String[][] HTML40_ARRAY = {
-//
- {"fnof", "402"}, //latin small f with hook = function= florin, U+0192 ISOtech -->
-//
- {"Alpha", "913"}, //greek capital letter alpha, U+0391 -->
- {"Beta", "914"}, //greek capital letter beta, U+0392 -->
- {"Gamma", "915"}, //greek capital letter gamma,U+0393 ISOgrk3 -->
- {"Delta", "916"}, //greek capital letter delta,U+0394 ISOgrk3 -->
- {"Epsilon", "917"}, //greek capital letter epsilon, U+0395 -->
- {"Zeta", "918"}, //greek capital letter zeta, U+0396 -->
- {"Eta", "919"}, //greek capital letter eta, U+0397 -->
- {"Theta", "920"}, //greek capital letter theta,U+0398 ISOgrk3 -->
- {"Iota", "921"}, //greek capital letter iota, U+0399 -->
- {"Kappa", "922"}, //greek capital letter kappa, U+039A -->
- {"Lambda", "923"}, //greek capital letter lambda,U+039B ISOgrk3 -->
- {"Mu", "924"}, //greek capital letter mu, U+039C -->
- {"Nu", "925"}, //greek capital letter nu, U+039D -->
- {"Xi", "926"}, //greek capital letter xi, U+039E ISOgrk3 -->
- {"Omicron", "927"}, //greek capital letter omicron, U+039F -->
- {"Pi", "928"}, //greek capital letter pi, U+03A0 ISOgrk3 -->
- {"Rho", "929"}, //greek capital letter rho, U+03A1 -->
-//
- {"Sigma", "931"}, //greek capital letter sigma,U+03A3 ISOgrk3 -->
- {"Tau", "932"}, //greek capital letter tau, U+03A4 -->
- {"Upsilon", "933"}, //greek capital letter upsilon,U+03A5 ISOgrk3 -->
- {"Phi", "934"}, //greek capital letter phi,U+03A6 ISOgrk3 -->
- {"Chi", "935"}, //greek capital letter chi, U+03A7 -->
- {"Psi", "936"}, //greek capital letter psi,U+03A8 ISOgrk3 -->
- {"Omega", "937"}, //greek capital letter omega,U+03A9 ISOgrk3 -->
- {"alpha", "945"}, //greek small letter alpha,U+03B1 ISOgrk3 -->
- {"beta", "946"}, //greek small letter beta, U+03B2 ISOgrk3 -->
- {"gamma", "947"}, //greek small letter gamma,U+03B3 ISOgrk3 -->
- {"delta", "948"}, //greek small letter delta,U+03B4 ISOgrk3 -->
- {"epsilon", "949"}, //greek small letter epsilon,U+03B5 ISOgrk3 -->
- {"zeta", "950"}, //greek small letter zeta, U+03B6 ISOgrk3 -->
- {"eta", "951"}, //greek small letter eta, U+03B7 ISOgrk3 -->
- {"theta", "952"}, //greek small letter theta,U+03B8 ISOgrk3 -->
- {"iota", "953"}, //greek small letter iota, U+03B9 ISOgrk3 -->
- {"kappa", "954"}, //greek small letter kappa,U+03BA ISOgrk3 -->
- {"lambda", "955"}, //greek small letter lambda,U+03BB ISOgrk3 -->
- {"mu", "956"}, //greek small letter mu, U+03BC ISOgrk3 -->
- {"nu", "957"}, //greek small letter nu, U+03BD ISOgrk3 -->
- {"xi", "958"}, //greek small letter xi, U+03BE ISOgrk3 -->
- {"omicron", "959"}, //greek small letter omicron, U+03BF NEW -->
- {"pi", "960"}, //greek small letter pi, U+03C0 ISOgrk3 -->
- {"rho", "961"}, //greek small letter rho, U+03C1 ISOgrk3 -->
- {"sigmaf", "962"}, //greek small letter final sigma,U+03C2 ISOgrk3 -->
- {"sigma", "963"}, //greek small letter sigma,U+03C3 ISOgrk3 -->
- {"tau", "964"}, //greek small letter tau, U+03C4 ISOgrk3 -->
- {"upsilon", "965"}, //greek small letter upsilon,U+03C5 ISOgrk3 -->
- {"phi", "966"}, //greek small letter phi, U+03C6 ISOgrk3 -->
- {"chi", "967"}, //greek small letter chi, U+03C7 ISOgrk3 -->
- {"psi", "968"}, //greek small letter psi, U+03C8 ISOgrk3 -->
- {"omega", "969"}, //greek small letter omega,U+03C9 ISOgrk3 -->
- {"thetasym", "977"}, //greek small letter theta symbol,U+03D1 NEW -->
- {"upsih", "978"}, //greek upsilon with hook symbol,U+03D2 NEW -->
- {"piv", "982"}, //greek pi symbol, U+03D6 ISOgrk3 -->
-//
- {"bull", "8226"}, //bullet = black small circle,U+2022 ISOpub -->
-//
- {"hellip", "8230"}, //horizontal ellipsis = three dot leader,U+2026 ISOpub -->
- {"prime", "8242"}, //prime = minutes = feet, U+2032 ISOtech -->
- {"Prime", "8243"}, //double prime = seconds = inches,U+2033 ISOtech -->
- {"oline", "8254"}, //overline = spacing overscore,U+203E NEW -->
- {"frasl", "8260"}, //fraction slash, U+2044 NEW -->
-//
- {"weierp", "8472"}, //script capital P = power set= Weierstrass p, U+2118 ISOamso -->
- {"image", "8465"}, //blackletter capital I = imaginary part,U+2111 ISOamso -->
- {"real", "8476"}, //blackletter capital R = real part symbol,U+211C ISOamso -->
- {"trade", "8482"}, //trade mark sign, U+2122 ISOnum -->
- {"alefsym", "8501"}, //alef symbol = first transfinite cardinal,U+2135 NEW -->
-//
-//
- {"larr", "8592"}, //leftwards arrow, U+2190 ISOnum -->
- {"uarr", "8593"}, //upwards arrow, U+2191 ISOnum-->
- {"rarr", "8594"}, //rightwards arrow, U+2192 ISOnum -->
- {"darr", "8595"}, //downwards arrow, U+2193 ISOnum -->
- {"harr", "8596"}, //left right arrow, U+2194 ISOamsa -->
- {"crarr", "8629"}, //downwards arrow with corner leftwards= carriage return, U+21B5 NEW -->
- {"lArr", "8656"}, //leftwards double arrow, U+21D0 ISOtech -->
-//
- {"uArr", "8657"}, //upwards double arrow, U+21D1 ISOamsa -->
- {"rArr", "8658"}, //rightwards double arrow,U+21D2 ISOtech -->
-//
- {"dArr", "8659"}, //downwards double arrow, U+21D3 ISOamsa -->
- {"hArr", "8660"}, //left right double arrow,U+21D4 ISOamsa -->
-//
- {"forall", "8704"}, //for all, U+2200 ISOtech -->
- {"part", "8706"}, //partial differential, U+2202 ISOtech -->
- {"exist", "8707"}, //there exists, U+2203 ISOtech -->
- {"empty", "8709"}, //empty set = null set = diameter,U+2205 ISOamso -->
- {"nabla", "8711"}, //nabla = backward difference,U+2207 ISOtech -->
- {"isin", "8712"}, //element of, U+2208 ISOtech -->
- {"notin", "8713"}, //not an element of, U+2209 ISOtech -->
- {"ni", "8715"}, //contains as member, U+220B ISOtech -->
-//
- {"prod", "8719"}, //n-ary product = product sign,U+220F ISOamsb -->
-//
- {"sum", "8721"}, //n-ary sumation, U+2211 ISOamsb -->
-//
- {"minus", "8722"}, //minus sign, U+2212 ISOtech -->
- {"lowast", "8727"}, //asterisk operator, U+2217 ISOtech -->
- {"radic", "8730"}, //square root = radical sign,U+221A ISOtech -->
- {"prop", "8733"}, //proportional to, U+221D ISOtech -->
- {"infin", "8734"}, //infinity, U+221E ISOtech -->
- {"ang", "8736"}, //angle, U+2220 ISOamso -->
- {"and", "8743"}, //logical and = wedge, U+2227 ISOtech -->
- {"or", "8744"}, //logical or = vee, U+2228 ISOtech -->
- {"cap", "8745"}, //intersection = cap, U+2229 ISOtech -->
- {"cup", "8746"}, //union = cup, U+222A ISOtech -->
- {"int", "8747"}, //integral, U+222B ISOtech -->
- {"there4", "8756"}, //therefore, U+2234 ISOtech -->
- {"sim", "8764"}, //tilde operator = varies with = similar to,U+223C ISOtech -->
-//
- {"cong", "8773"}, //approximately equal to, U+2245 ISOtech -->
- {"asymp", "8776"}, //almost equal to = asymptotic to,U+2248 ISOamsr -->
- {"ne", "8800"}, //not equal to, U+2260 ISOtech -->
- {"equiv", "8801"}, //identical to, U+2261 ISOtech -->
- {"le", "8804"}, //less-than or equal to, U+2264 ISOtech -->
- {"ge", "8805"}, //greater-than or equal to,U+2265 ISOtech -->
- {"sub", "8834"}, //subset of, U+2282 ISOtech -->
- {"sup", "8835"}, //superset of, U+2283 ISOtech -->
-//
- {"sube", "8838"}, //subset of or equal to, U+2286 ISOtech -->
- {"supe", "8839"}, //superset of or equal to,U+2287 ISOtech -->
- {"oplus", "8853"}, //circled plus = direct sum,U+2295 ISOamsb -->
- {"otimes", "8855"}, //circled times = vector product,U+2297 ISOamsb -->
- {"perp", "8869"}, //up tack = orthogonal to = perpendicular,U+22A5 ISOtech -->
- {"sdot", "8901"}, //dot operator, U+22C5 ISOamsb -->
-//
-//
- {"lceil", "8968"}, //left ceiling = apl upstile,U+2308 ISOamsc -->
- {"rceil", "8969"}, //right ceiling, U+2309 ISOamsc -->
- {"lfloor", "8970"}, //left floor = apl downstile,U+230A ISOamsc -->
- {"rfloor", "8971"}, //right floor, U+230B ISOamsc -->
- {"lang", "9001"}, //left-pointing angle bracket = bra,U+2329 ISOtech -->
-//
- {"rang", "9002"}, //right-pointing angle bracket = ket,U+232A ISOtech -->
-//
-//
- {"loz", "9674"}, //lozenge, U+25CA ISOpub -->
-//
- {"spades", "9824"}, //black spade suit, U+2660 ISOpub -->
-//
- {"clubs", "9827"}, //black club suit = shamrock,U+2663 ISOpub -->
- {"hearts", "9829"}, //black heart suit = valentine,U+2665 ISOpub -->
- {"diams", "9830"}, //black diamond suit, U+2666 ISOpub -->
+ //
+ {"fnof", "402"}, // latin small f with hook = function= florin, U+0192 ISOtech -->
+ //
+ {"Alpha", "913"}, // greek capital letter alpha, U+0391 -->
+ {"Beta", "914"}, // greek capital letter beta, U+0392 -->
+ {"Gamma", "915"}, // greek capital letter gamma,U+0393 ISOgrk3 -->
+ {"Delta", "916"}, // greek capital letter delta,U+0394 ISOgrk3 -->
+ {"Epsilon", "917"}, // greek capital letter epsilon, U+0395 -->
+ {"Zeta", "918"}, // greek capital letter zeta, U+0396 -->
+ {"Eta", "919"}, // greek capital letter eta, U+0397 -->
+ {"Theta", "920"}, // greek capital letter theta,U+0398 ISOgrk3 -->
+ {"Iota", "921"}, // greek capital letter iota, U+0399 -->
+ {"Kappa", "922"}, // greek capital letter kappa, U+039A -->
+ {"Lambda", "923"}, // greek capital letter lambda,U+039B ISOgrk3 -->
+ {"Mu", "924"}, // greek capital letter mu, U+039C -->
+ {"Nu", "925"}, // greek capital letter nu, U+039D -->
+ {"Xi", "926"}, // greek capital letter xi, U+039E ISOgrk3 -->
+ {"Omicron", "927"}, // greek capital letter omicron, U+039F -->
+ {"Pi", "928"}, // greek capital letter pi, U+03A0 ISOgrk3 -->
+ {"Rho", "929"}, // greek capital letter rho, U+03A1 -->
+ //
+ {"Sigma", "931"}, // greek capital letter sigma,U+03A3 ISOgrk3 -->
+ {"Tau", "932"}, // greek capital letter tau, U+03A4 -->
+ {"Upsilon", "933"}, // greek capital letter upsilon,U+03A5 ISOgrk3 -->
+ {"Phi", "934"}, // greek capital letter phi,U+03A6 ISOgrk3 -->
+ {"Chi", "935"}, // greek capital letter chi, U+03A7 -->
+ {"Psi", "936"}, // greek capital letter psi,U+03A8 ISOgrk3 -->
+ {"Omega", "937"}, // greek capital letter omega,U+03A9 ISOgrk3 -->
+ {"alpha", "945"}, // greek small letter alpha,U+03B1 ISOgrk3 -->
+ {"beta", "946"}, // greek small letter beta, U+03B2 ISOgrk3 -->
+ {"gamma", "947"}, // greek small letter gamma,U+03B3 ISOgrk3 -->
+ {"delta", "948"}, // greek small letter delta,U+03B4 ISOgrk3 -->
+ {"epsilon", "949"}, // greek small letter epsilon,U+03B5 ISOgrk3 -->
+ {"zeta", "950"}, // greek small letter zeta, U+03B6 ISOgrk3 -->
+ {"eta", "951"}, // greek small letter eta, U+03B7 ISOgrk3 -->
+ {"theta", "952"}, // greek small letter theta,U+03B8 ISOgrk3 -->
+ {"iota", "953"}, // greek small letter iota, U+03B9 ISOgrk3 -->
+ {"kappa", "954"}, // greek small letter kappa,U+03BA ISOgrk3 -->
+ {"lambda", "955"}, // greek small letter lambda,U+03BB ISOgrk3 -->
+ {"mu", "956"}, // greek small letter mu, U+03BC ISOgrk3 -->
+ {"nu", "957"}, // greek small letter nu, U+03BD ISOgrk3 -->
+ {"xi", "958"}, // greek small letter xi, U+03BE ISOgrk3 -->
+ {"omicron", "959"}, // greek small letter omicron, U+03BF NEW -->
+ {"pi", "960"}, // greek small letter pi, U+03C0 ISOgrk3 -->
+ {"rho", "961"}, // greek small letter rho, U+03C1 ISOgrk3 -->
+ {"sigmaf", "962"}, // greek small letter final sigma,U+03C2 ISOgrk3 -->
+ {"sigma", "963"}, // greek small letter sigma,U+03C3 ISOgrk3 -->
+ {"tau", "964"}, // greek small letter tau, U+03C4 ISOgrk3 -->
+ {"upsilon", "965"}, // greek small letter upsilon,U+03C5 ISOgrk3 -->
+ {"phi", "966"}, // greek small letter phi, U+03C6 ISOgrk3 -->
+ {"chi", "967"}, // greek small letter chi, U+03C7 ISOgrk3 -->
+ {"psi", "968"}, // greek small letter psi, U+03C8 ISOgrk3 -->
+ {"omega", "969"}, // greek small letter omega,U+03C9 ISOgrk3 -->
+ {"thetasym", "977"}, // greek small letter theta symbol,U+03D1 NEW -->
+ {"upsih", "978"}, // greek upsilon with hook symbol,U+03D2 NEW -->
+ {"piv", "982"}, // greek pi symbol, U+03D6 ISOgrk3 -->
+ //
+ {"bull", "8226"}, // bullet = black small circle,U+2022 ISOpub -->
+ //
+ {"hellip", "8230"}, // horizontal ellipsis = three dot leader,U+2026 ISOpub -->
+ {"prime", "8242"}, // prime = minutes = feet, U+2032 ISOtech -->
+ {"Prime", "8243"}, // double prime = seconds = inches,U+2033 ISOtech -->
+ {"oline", "8254"}, // overline = spacing overscore,U+203E NEW -->
+ {"frasl", "8260"}, // fraction slash, U+2044 NEW -->
+ //
+ {"weierp", "8472"}, // script capital P = power set= Weierstrass p, U+2118 ISOamso -->
+ {"image", "8465"}, // blackletter capital I = imaginary part,U+2111 ISOamso -->
+ {"real", "8476"}, // blackletter capital R = real part symbol,U+211C ISOamso -->
+ {"trade", "8482"}, // trade mark sign, U+2122 ISOnum -->
+ {"alefsym", "8501"}, // alef symbol = first transfinite cardinal,U+2135 NEW -->
+ //
+ //
+ {"larr", "8592"}, // leftwards arrow, U+2190 ISOnum -->
+ {"uarr", "8593"}, // upwards arrow, U+2191 ISOnum-->
+ {"rarr", "8594"}, // rightwards arrow, U+2192 ISOnum -->
+ {"darr", "8595"}, // downwards arrow, U+2193 ISOnum -->
+ {"harr", "8596"}, // left right arrow, U+2194 ISOamsa -->
+ {"crarr", "8629"}, // downwards arrow with corner leftwards= carriage return, U+21B5 NEW -->
+ {"lArr", "8656"}, // leftwards double arrow, U+21D0 ISOtech -->
+ //
+ {"uArr", "8657"}, // upwards double arrow, U+21D1 ISOamsa -->
+ {"rArr", "8658"}, // rightwards double arrow,U+21D2 ISOtech -->
+ //
+ {"dArr", "8659"}, // downwards double arrow, U+21D3 ISOamsa -->
+ {"hArr", "8660"}, // left right double arrow,U+21D4 ISOamsa -->
+ //
+ {"forall", "8704"}, // for all, U+2200 ISOtech -->
+ {"part", "8706"}, // partial differential, U+2202 ISOtech -->
+ {"exist", "8707"}, // there exists, U+2203 ISOtech -->
+ {"empty", "8709"}, // empty set = null set = diameter,U+2205 ISOamso -->
+ {"nabla", "8711"}, // nabla = backward difference,U+2207 ISOtech -->
+ {"isin", "8712"}, // element of, U+2208 ISOtech -->
+ {"notin", "8713"}, // not an element of, U+2209 ISOtech -->
+ {"ni", "8715"}, // contains as member, U+220B ISOtech -->
+ //
+ {"prod", "8719"}, // n-ary product = product sign,U+220F ISOamsb -->
+ //
+ {"sum", "8721"}, // n-ary summation, U+2211 ISOamsb -->
+ //
+ {"minus", "8722"}, // minus sign, U+2212 ISOtech -->
+ {"lowast", "8727"}, // asterisk operator, U+2217 ISOtech -->
+ {"radic", "8730"}, // square root = radical sign,U+221A ISOtech -->
+ {"prop", "8733"}, // proportional to, U+221D ISOtech -->
+ {"infin", "8734"}, // infinity, U+221E ISOtech -->
+ {"ang", "8736"}, // angle, U+2220 ISOamso -->
+ {"and", "8743"}, // logical and = wedge, U+2227 ISOtech -->
+ {"or", "8744"}, // logical or = vee, U+2228 ISOtech -->
+ {"cap", "8745"}, // intersection = cap, U+2229 ISOtech -->
+ {"cup", "8746"}, // union = cup, U+222A ISOtech -->
+ {"int", "8747"}, // integral, U+222B ISOtech -->
+ {"there4", "8756"}, // therefore, U+2234 ISOtech -->
+ {"sim", "8764"}, // tilde operator = varies with = similar to,U+223C ISOtech -->
+ //
+ {"cong", "8773"}, // approximately equal to, U+2245 ISOtech -->
+ {"asymp", "8776"}, // almost equal to = asymptotic to,U+2248 ISOamsr -->
+ {"ne", "8800"}, // not equal to, U+2260 ISOtech -->
+ {"equiv", "8801"}, // identical to, U+2261 ISOtech -->
+ {"le", "8804"}, // less-than or equal to, U+2264 ISOtech -->
+ {"ge", "8805"}, // greater-than or equal to,U+2265 ISOtech -->
+ {"sub", "8834"}, // subset of, U+2282 ISOtech -->
+ {"sup", "8835"}, // superset of, U+2283 ISOtech -->
+ //
+ {"sube", "8838"}, // subset of or equal to, U+2286 ISOtech -->
+ {"supe", "8839"}, // superset of or equal to,U+2287 ISOtech -->
+ {"oplus", "8853"}, // circled plus = direct sum,U+2295 ISOamsb -->
+ {"otimes", "8855"}, // circled times = vector product,U+2297 ISOamsb -->
+ {"perp", "8869"}, // up tack = orthogonal to = perpendicular,U+22A5 ISOtech -->
+ {"sdot", "8901"}, // dot operator, U+22C5 ISOamsb -->
+ //
+ //
+ {"lceil", "8968"}, // left ceiling = apl upstile,U+2308 ISOamsc -->
+ {"rceil", "8969"}, // right ceiling, U+2309 ISOamsc -->
+ {"lfloor", "8970"}, // left floor = apl downstile,U+230A ISOamsc -->
+ {"rfloor", "8971"}, // right floor, U+230B ISOamsc -->
+ {"lang", "9001"}, // left-pointing angle bracket = bra,U+2329 ISOtech -->
+ //
+ {"rang", "9002"}, // right-pointing angle bracket = ket,U+232A ISOtech -->
+ //
+ //
+ {"loz", "9674"}, // lozenge, U+25CA ISOpub -->
+ //
+ {"spades", "9824"}, // black spade suit, U+2660 ISOpub -->
+ //
+ {"clubs", "9827"}, // black club suit = shamrock,U+2663 ISOpub -->
+ {"hearts", "9829"}, // black heart suit = valentine,U+2665 ISOpub -->
+ {"diams", "9830"}, // black diamond suit, U+2666 ISOpub -->
-//
- {"OElig", "338"}, // -- latin capital ligature OE,U+0152 ISOlat2 -->
- {"oelig", "339"}, // -- latin small ligature oe, U+0153 ISOlat2 -->
-//
- {"Scaron", "352"}, // -- latin capital letter S with caron,U+0160 ISOlat2 -->
- {"scaron", "353"}, // -- latin small letter s with caron,U+0161 ISOlat2 -->
- {"Yuml", "376"}, // -- latin capital letter Y with diaeresis,U+0178 ISOlat2 -->
-//
- {"circ", "710"}, // -- modifier letter circumflex accent,U+02C6 ISOpub -->
- {"tilde", "732"}, //small tilde, U+02DC ISOdia -->
-//
- {"ensp", "8194"}, //en space, U+2002 ISOpub -->
- {"emsp", "8195"}, //em space, U+2003 ISOpub -->
- {"thinsp", "8201"}, //thin space, U+2009 ISOpub -->
- {"zwnj", "8204"}, //zero width non-joiner,U+200C NEW RFC 2070 -->
- {"zwj", "8205"}, //zero width joiner, U+200D NEW RFC 2070 -->
- {"lrm", "8206"}, //left-to-right mark, U+200E NEW RFC 2070 -->
- {"rlm", "8207"}, //right-to-left mark, U+200F NEW RFC 2070 -->
- {"ndash", "8211"}, //en dash, U+2013 ISOpub -->
- {"mdash", "8212"}, //em dash, U+2014 ISOpub -->
- {"lsquo", "8216"}, //left single quotation mark,U+2018 ISOnum -->
- {"rsquo", "8217"}, //right single quotation mark,U+2019 ISOnum -->
- {"sbquo", "8218"}, //single low-9 quotation mark, U+201A NEW -->
- {"ldquo", "8220"}, //left double quotation mark,U+201C ISOnum -->
- {"rdquo", "8221"}, //right double quotation mark,U+201D ISOnum -->
- {"bdquo", "8222"}, //double low-9 quotation mark, U+201E NEW -->
- {"dagger", "8224"}, //dagger, U+2020 ISOpub -->
- {"Dagger", "8225"}, //double dagger, U+2021 ISOpub -->
- {"permil", "8240"}, //per mille sign, U+2030 ISOtech -->
- {"lsaquo", "8249"}, //single left-pointing angle quotation mark,U+2039 ISO proposed -->
-//
- {"rsaquo", "8250"}, //single right-pointing angle quotation mark,U+203A ISO proposed -->
-//
- {"euro", "8364"}, // -- euro sign, U+20AC NEW -->
+ //
+ {"OElig", "338"}, // -- latin capital ligature OE,U+0152 ISOlat2 -->
+ {"oelig", "339"}, // -- latin small ligature oe, U+0153 ISOlat2 -->
+ //
+ {"Scaron", "352"}, // -- latin capital letter S with caron,U+0160 ISOlat2 -->
+ {"scaron", "353"}, // -- latin small letter s with caron,U+0161 ISOlat2 -->
+ {"Yuml", "376"}, // -- latin capital letter Y with diaeresis,U+0178 ISOlat2 -->
+ //
+ {"circ", "710"}, // -- modifier letter circumflex accent,U+02C6 ISOpub -->
+ {"tilde", "732"}, // small tilde, U+02DC ISOdia -->
+ //
+ {"ensp", "8194"}, // en space, U+2002 ISOpub -->
+ {"emsp", "8195"}, // em space, U+2003 ISOpub -->
+ {"thinsp", "8201"}, // thin space, U+2009 ISOpub -->
+ {"zwnj", "8204"}, // zero width non-joiner,U+200C NEW RFC 2070 -->
+ {"zwj", "8205"}, // zero width joiner, U+200D NEW RFC 2070 -->
+ {"lrm", "8206"}, // left-to-right mark, U+200E NEW RFC 2070 -->
+ {"rlm", "8207"}, // right-to-left mark, U+200F NEW RFC 2070 -->
+ {"ndash", "8211"}, // en dash, U+2013 ISOpub -->
+ {"mdash", "8212"}, // em dash, U+2014 ISOpub -->
+ {"lsquo", "8216"}, // left single quotation mark,U+2018 ISOnum -->
+ {"rsquo", "8217"}, // right single quotation mark,U+2019 ISOnum -->
+ {"sbquo", "8218"}, // single low-9 quotation mark, U+201A NEW -->
+ {"ldquo", "8220"}, // left double quotation mark,U+201C ISOnum -->
+ {"rdquo", "8221"}, // right double quotation mark,U+201D ISOnum -->
+ {"bdquo", "8222"}, // double low-9 quotation mark, U+201E NEW -->
+ {"dagger", "8224"}, // dagger, U+2020 ISOpub -->
+ {"Dagger", "8225"}, // double dagger, U+2021 ISOpub -->
+ {"permil", "8240"}, // per mille sign, U+2030 ISOtech -->
+ {"lsaquo", "8249"}, // single left-pointing angle quotation mark,U+2039 ISO proposed -->
+ //
+ {"rsaquo", "8250"}, // single right-pointing angle quotation mark,U+203A ISO proposed -->
+ //
+ {"euro", "8364"}, // -- euro sign, U+20AC NEW -->
};
/**
- * The set of entities supported by standard XML.
+ *
+ * The set of entities supported by standard XML.
+ *
*/
public static final Entities XML;
/**
- * The set of entities supported by HTML 3.2.
+ *
+ * The set of entities supported by HTML 3.2.
+ *
*/
public static final Entities HTML32;
/**
- * The set of entities supported by HTML 4.0.
+ *
+ * The set of entities supported by HTML 4.0.
+ *
*/
public static final Entities HTML40;
static {
- XML = new Entities();
- XML.addEntities(BASIC_ARRAY);
- XML.addEntities(APOS_ARRAY);
+ Entities xml = new Entities();
+ xml.addEntities(BASIC_ARRAY);
+ xml.addEntities(APOS_ARRAY);
+ XML = xml;
}
static {
- HTML32 = new Entities();
- HTML32.addEntities(BASIC_ARRAY);
- HTML32.addEntities(ISO8859_1_ARRAY);
+ Entities html32 = new Entities();
+ html32.addEntities(BASIC_ARRAY);
+ html32.addEntities(ISO8859_1_ARRAY);
+ HTML32 = html32;
}
static {
- HTML40 = new Entities();
- fillWithHtml40Entities(HTML40);
+ Entities html40 = new Entities();
+ fillWithHtml40Entities(html40);
+ HTML40 = html40;
}
+ /**
+ *
+ * Fills the specified entities instance with HTML 40 entities.
+ *
+ *
+ * @param entities
+ * the instance to be filled.
+ */
static void fillWithHtml40Entities(Entities entities) {
entities.addEntities(BASIC_ARRAY);
entities.addEntities(ISO8859_1_ARRAY);
entities.addEntities(HTML40_ARRAY);
}
static interface EntityMap {
+ /**
+ *
+ * Add an entry to this entity map.
+ *
+ *
+ * @param name
+ * the entity name
+ * @param value
+ * the entity value
+ */
void add(String name, int value);
+ /**
+ *
+ * Returns the name of the entity identified by the specified value.
+ *
+ *
+ * @param value
+ * the value to locate
+ * @return entity name associated with the specified value
+ */
String name(int value);
+ /**
+ *
+ * Returns the value of the entity identified by the specified name.
+ *
+ *
+ * @param name
+ * the name to locate
+ * @return entity value associated with the specified name
+ */
int value(String name);
}
static class PrimitiveEntityMap implements EntityMap {
- private Map mapNameToValue = new HashMap();
- private IntHashMap mapValueToName = new IntHashMap();
+ private final Map mapNameToValue = new HashMap();
+ private final IntHashMap mapValueToName = new IntHashMap();
+
+ /**
+ * {@inheritDoc}
+ */
+ // TODO not thread-safe as there is a window between changing the two maps
public void add(String name, int value) {
mapNameToValue.put(name, new Integer(value));
mapValueToName.put(value, name);
}
+ /**
+ * {@inheritDoc}
+ */
public String name(int value) {
return (String) mapValueToName.get(value);
}
+ /**
+ * {@inheritDoc}
+ */
public int value(String name) {
Object value = mapNameToValue.get(name);
- if (value == null)
+ if (value == null) {
return -1;
+ }
return ((Integer) value).intValue();
}
}
-
static abstract class MapIntMap implements Entities.EntityMap {
- protected Map mapNameToValue;
- protected Map mapValueToName;
+ protected final Map mapNameToValue;
+ protected final Map mapValueToName;
+
+ /**
+ * Construct a new instance with specified maps.
+ *
+ * @param nameToValue name to value map
+ * @param valueToName value to namee map
+ */
+ MapIntMap(Map nameToValue, Map valueToName){
+ mapNameToValue = nameToValue;
+ mapValueToName = valueToName;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public void add(String name, int value) {
mapNameToValue.put(name, new Integer(value));
mapValueToName.put(new Integer(value), name);
}
+ /**
+ * {@inheritDoc}
+ */
public String name(int value) {
return (String) mapValueToName.get(new Integer(value));
}
+ /**
+ * {@inheritDoc}
+ */
public int value(String name) {
Object value = mapNameToValue.get(name);
- if (value == null)
+ if (value == null) {
return -1;
+ }
return ((Integer) value).intValue();
}
}
static class HashEntityMap extends MapIntMap {
+ /**
+ * Constructs a new instance of HashEntityMap
.
+ */
public HashEntityMap() {
- mapNameToValue = new HashMap();
- mapValueToName = new HashMap();
+ super(new HashMap(), new HashMap());
}
}
static class TreeEntityMap extends MapIntMap {
+ /**
+ * Constructs a new instance of TreeEntityMap
.
+ */
public TreeEntityMap() {
- mapNameToValue = new TreeMap();
- mapValueToName = new TreeMap();
+ super(new TreeMap(), new TreeMap());
}
}
static class LookupEntityMap extends PrimitiveEntityMap {
+ // TODO this class is not thread-safe
private String[] lookupTable;
- private int LOOKUP_TABLE_SIZE = 256;
+ private static final int LOOKUP_TABLE_SIZE = 256;
+
+ /**
+ * {@inheritDoc}
+ */
public String name(int value) {
if (value < LOOKUP_TABLE_SIZE) {
return lookupTable()[value];
}
return super.name(value);
}
+ /**
+ *
+ * Returns the lookup table for this entity map. The lookup table is created if it has not been previously.
+ *
+ *
+ * @return the lookup table
+ */
private String[] lookupTable() {
if (lookupTable == null) {
createLookupTable();
}
return lookupTable;
}
+ /**
+ *
+ * Creates an entity lookup table of LOOKUP_TABLE_SIZE elements, initialized with entity names.
+ *
+ */
private void createLookupTable() {
lookupTable = new String[LOOKUP_TABLE_SIZE];
for (int i = 0; i < LOOKUP_TABLE_SIZE; ++i) {
@@ -500,29 +578,53 @@
}
static class ArrayEntityMap implements EntityMap {
- protected int growBy = 100;
+ // TODO this class is not thread-safe
+ protected final int growBy;
+
protected int size = 0;
+
protected String[] names;
+
protected int[] values;
+ /**
+ * Constructs a new instance of ArrayEntityMap
.
+ */
public ArrayEntityMap() {
+ this.growBy = 100;
names = new String[growBy];
values = new int[growBy];
}
+ /**
+ * Constructs a new instance of ArrayEntityMap
specifying the size by which the array should
+ * grow.
+ *
+ * @param growBy
+ * array will be initialized to and will grow by this amount
+ */
public ArrayEntityMap(int growBy) {
this.growBy = growBy;
names = new String[growBy];
values = new int[growBy];
}
+ /**
+ * {@inheritDoc}
+ */
public void add(String name, int value) {
ensureCapacity(size + 1);
names[size] = name;
values[size] = value;
size++;
}
+ /**
+ * Verifies the capacity of the entity array, adjusting the size if necessary.
+ *
+ * @param capacity
+ * size the array should be
+ */
protected void ensureCapacity(int capacity) {
if (capacity > names.length) {
int newSize = Math.max(capacity, size + growBy);
@@ -535,6 +637,9 @@
}
}
+ /**
+ * {@inheritDoc}
+ */
public String name(int value) {
for (int i = 0; i < size; ++i) {
if (values[i] == value) {
@@ -544,6 +649,9 @@
return null;
}
+ /**
+ * {@inheritDoc}
+ */
public int value(String name) {
for (int i = 0; i < size; ++i) {
if (names[i].equals(name)) {
@@ -556,147 +664,360 @@
static class BinaryEntityMap extends ArrayEntityMap {
+ // TODO - not thread-safe, because parent is not. Also references size.
+
+ /**
+ * Constructs a new instance of BinaryEntityMap
.
+ */
public BinaryEntityMap() {
+ super();
}
+ /**
+ * Constructs a new instance of ArrayEntityMap
specifying the size by which the underlying array
+ * should grow.
+ *
+ * @param growBy
+ * array will be initialized to and will grow by this amount
+ */
public BinaryEntityMap(int growBy) {
super(growBy);
}
- // based on code in java.util.Arrays
+ /**
+ * Performs a binary search of the entity array for the specified key. This method is based on code in
+ * {@link java.util.Arrays}.
+ *
+ * @param key
+ * the key to be found
+ * @return the index of the entity array matching the specified key
+ */
private int binarySearch(int key) {
int low = 0;
int high = size - 1;
while (low <= high) {
- int mid = (low + high) >> 1;
+ int mid = (low + high) >>> 1;
int midVal = values[mid];
- if (midVal < key)
+ if (midVal < key) {
low = mid + 1;
- else if (midVal > key)
+ } else if (midVal > key) {
high = mid - 1;
- else
+ } else {
return mid; // key found
+ }
}
- return -(low + 1); // key not found.
+ return -(low + 1); // key not found.
}
+ /**
+ * {@inheritDoc}
+ */
public void add(String name, int value) {
ensureCapacity(size + 1);
int insertAt = binarySearch(value);
- if (insertAt > 0) return; // note: this means you can't insert the same value twice
- insertAt = -(insertAt + 1); // binarySearch returns it negative and off-by-one
+ if (insertAt > 0) {
+ return; // note: this means you can't insert the same value twice
+ }
+ insertAt = -(insertAt + 1); // binarySearch returns it negative and off-by-one
System.arraycopy(values, insertAt, values, insertAt + 1, size - insertAt);
values[insertAt] = value;
System.arraycopy(names, insertAt, names, insertAt + 1, size - insertAt);
names[insertAt] = name;
size++;
}
+ /**
+ * {@inheritDoc}
+ */
public String name(int value) {
int index = binarySearch(value);
- if (index < 0) return null;
+ if (index < 0) {
+ return null;
+ }
return names[index];
}
}
- // package scoped for testing
- EntityMap map = new Entities.LookupEntityMap();
+ private final EntityMap map;
+ /**
+ * Default constructor.
+ */
+ public Entities(){
+ map = new Entities.LookupEntityMap();
+ }
+
+ /**
+ * package scoped constructor for testing.
+ *
+ * @param emap entity map.
+ */
+ Entities(EntityMap emap){
+ map = emap;
+ }
+
+ /**
+ *
+ * Adds entities to this entity.
+ *
+ *
+ * @param entityArray
+ * array of entities to be added
+ */
public void addEntities(String[][] entityArray) {
for (int i = 0; i < entityArray.length; ++i) {
addEntity(entityArray[i][0], Integer.parseInt(entityArray[i][1]));
}
}
+ /**
+ *
+ * Add an entity to this entity.
+ *
+ *
+ * @param name
+ * name of the entity
+ * @param value
+ * vale of the entity
+ */
public void addEntity(String name, int value) {
map.add(name, value);
}
+ /**
+ *
+ * Returns the name of the entity identified by the specified value.
+ *
+ *
+ * @param value
+ * the value to locate
+ * @return entity name associated with the specified value
+ */
public String entityName(int value) {
return map.name(value);
}
-
+ /**
+ *
+ * Returns the value of the entity identified by the specified name.
+ *
+ *
+ * @param name
+ * the name to locate
+ * @return entity value associated with the specified name
+ */
public int entityValue(String name) {
return map.value(name);
}
/**
- * Escapes the characters in a String
.
- *
- * For example, if you have called addEntity("foo", 0xA1),
- * escape("\u00A1") will return "&foo;"
- *
- * @param str The String
to escape.
+ *
+ * Escapes the characters in a String
.
+ *
+ *
+ *
+ * For example, if you have called addEntity("foo", 0xA1), escape("\u00A1") will return
+ * "&foo;"
+ *
+ *
+ * @param str
+ * The String
to escape.
* @return A new escaped String
.
*/
public String escape(String str) {
- //todo: rewrite to use a Writer
- StringBuffer buf = new StringBuffer(str.length() * 2);
- int i;
- for (i = 0; i < str.length(); ++i) {
- char ch = str.charAt(i);
- String entityName = this.entityName(ch);
+ StringWriter stringWriter = createStringWriter(str);
+ try {
+ this.escape(stringWriter, str);
+ } catch (IOException e) {
+ // This should never happen because ALL the StringWriter methods called by #escape(Writer, String) do not
+ // throw IOExceptions.
+ throw new UnhandledException(e);
+ }
+ return stringWriter.toString();
+ }
+
+ /**
+ *
+ * Escapes the characters in the String
passed and writes the result to the Writer
+ * passed.
+ *
+ *
+ * @param writer
+ * The Writer
to write the results of the escaping to. Assumed to be a non-null value.
+ * @param str
+ * The String
to escape. Assumed to be a non-null value.
+ * @throws IOException
+ * when Writer
passed throws the exception from calls to the {@link Writer#write(int)}
+ * methods.
+ *
+ * @see #escape(String)
+ * @see Writer
+ */
+ public void escape(Writer writer, String str) throws IOException {
+ int len = str.length();
+ for (int i = 0; i < len; i++) {
+ char c = str.charAt(i);
+ String entityName = this.entityName(c);
if (entityName == null) {
- if (ch > 0x7F) {
- int intValue = ch;
- buf.append("");
- buf.append(intValue);
- buf.append(';');
+ if (c > 0x7F) {
+ writer.write("");
+ writer.write(Integer.toString(c, 10));
+ writer.write(';');
} else {
- buf.append(ch);
+ writer.write(c);
}
} else {
- buf.append('&');
- buf.append(entityName);
- buf.append(';');
+ writer.write('&');
+ writer.write(entityName);
+ writer.write(';');
}
}
- return buf.toString();
}
/**
- * Unescapes the entities in a String
.
- *
- * For example, if you have called addEntity("foo", 0xA1),
- * unescape("&foo;") will return "\u00A1"
- *
- * @param str The String
to escape.
+ *
+ * Unescapes the entities in a String
.
+ *
+ *
+ *
+ * For example, if you have called addEntity("foo", 0xA1), unescape("&foo;") will return
+ * "\u00A1"
+ *
+ *
+ * @param str
+ * The String
to escape.
* @return A new escaped String
.
*/
public String unescape(String str) {
- StringBuffer buf = new StringBuffer(str.length());
- int i;
- for (i = 0; i < str.length(); ++i) {
- char ch = str.charAt(i);
- if (ch == '&') {
- int semi = str.indexOf(';', i + 1);
- if (semi == -1) {
- buf.append(ch);
+ int firstAmp = str.indexOf('&');
+ if (firstAmp < 0) {
+ return str;
+ } else {
+ StringWriter stringWriter = createStringWriter(str);
+ try {
+ this.doUnescape(stringWriter, str, firstAmp);
+ } catch (IOException e) {
+ // This should never happen because ALL the StringWriter methods called by #escape(Writer, String)
+ // do not throw IOExceptions.
+ throw new UnhandledException(e);
+ }
+ return stringWriter.toString();
+ }
+ }
+
+ /**
+ * Make the StringWriter 10% larger than the source String to avoid growing the writer
+ *
+ * @param str The source string
+ * @return A newly created StringWriter
+ */
+ private StringWriter createStringWriter(String str) {
+ return new StringWriter((int) (str.length() + (str.length() * 0.1)));
+ }
+
+ /**
+ *
+ * Unescapes the escaped entities in the String
passed and writes the result to the
+ * Writer
passed.
+ *
+ *
+ * @param writer
+ * The Writer
to write the results to; assumed to be non-null.
+ * @param str
+ * The source String
to unescape; assumed to be non-null.
+ * @throws IOException
+ * when Writer
passed throws the exception from calls to the {@link Writer#write(int)}
+ * methods.
+ *
+ * @see #escape(String)
+ * @see Writer
+ */
+ public void unescape(Writer writer, String str) throws IOException {
+ int firstAmp = str.indexOf('&');
+ if (firstAmp < 0) {
+ writer.write(str);
+ return;
+ } else {
+ doUnescape(writer, str, firstAmp);
+ }
+ }
+
+ /**
+ * Underlying unescape method that allows the optimisation of not starting from the 0 index again.
+ *
+ * @param writer
+ * The Writer
to write the results to; assumed to be non-null.
+ * @param str
+ * The source String
to unescape; assumed to be non-null.
+ * @param firstAmp
+ * The int
index of the first ampersand in the source String.
+ * @throws IOException
+ * when Writer
passed throws the exception from calls to the {@link Writer#write(int)}
+ * methods.
+ */
+ private void doUnescape(Writer writer, String str, int firstAmp) throws IOException {
+ writer.write(str, 0, firstAmp);
+ int len = str.length();
+ for (int i = firstAmp; i < len; i++) {
+ char c = str.charAt(i);
+ if (c == '&') {
+ int nextIdx = i + 1;
+ int semiColonIdx = str.indexOf(';', nextIdx);
+ if (semiColonIdx == -1) {
+ writer.write(c);
continue;
}
- String entityName = str.substring(i + 1, semi);
- int entityValue;
- if (entityName.charAt(0) == '#') {
- entityValue = Integer.parseInt(entityName.substring(1));
- } else {
- entityValue = this.entityValue(entityName);
+ int amphersandIdx = str.indexOf('&', i + 1);
+ if (amphersandIdx != -1 && amphersandIdx < semiColonIdx) {
+ // Then the text looks like &...&...;
+ writer.write(c);
+ continue;
}
+ String entityContent = str.substring(nextIdx, semiColonIdx);
+ int entityValue = -1;
+ int entityContentLen = entityContent.length();
+ if (entityContentLen > 0) {
+ if (entityContent.charAt(0) == '#') { // escaped value content is an integer (decimal or
+ // hexidecimal)
+ if (entityContentLen > 1) {
+ char isHexChar = entityContent.charAt(1);
+ try {
+ switch (isHexChar) {
+ case 'X' :
+ case 'x' : {
+ entityValue = Integer.parseInt(entityContent.substring(2), 16);
+ break;
+ }
+ default : {
+ entityValue = Integer.parseInt(entityContent.substring(1), 10);
+ }
+ }
+ if (entityValue > 0xFFFF) {
+ entityValue = -1;
+ }
+ } catch (NumberFormatException e) {
+ entityValue = -1;
+ }
+ }
+ } else { // escaped value content is an entity name
+ entityValue = this.entityValue(entityContent);
+ }
+ }
+
if (entityValue == -1) {
- buf.append('&');
- buf.append(entityName);
- buf.append(';');
+ writer.write('&');
+ writer.write(entityContent);
+ writer.write(';');
} else {
- buf.append((char) (entityValue));
+ writer.write(entityValue);
}
- i = semi;
+ i = semiColonIdx; // move index up to the semi-colon
} else {
- buf.append(ch);
+ writer.write(c);
}
}
- return buf.toString();
}
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/IllegalClassException.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/IllegalClassException.java (.../IllegalClassException.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/IllegalClassException.java (.../IllegalClassException.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,61 +1,42 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang;
/**
- * Thrown when an object is an instance of an unexpected type (a class or interface).
+ * Thrown when an object is an instance of an unexpected type (a class or interface).
+ * This exception supplements the standard IllegalArgumentException
+ * by providing a more semantically rich description of the problem.
*
+ * IllegalClassException
represents the case where a method takes
+ * in a genericly typed parameter like Object (typically because it has to due to some
+ * other interface it implements), but this implementation only actually accepts a specific
+ * type, for example String. This exception would be used in place of
+ * IllegalArgumentException
, yet it still extends it.
+ *
+ *
+ * public void foo(Object obj) {
+ * if (obj instanceof String == false) {
+ * throw new IllegalClassException(String.class, obj);
+ * }
+ * // do something with the string
+ * }
+ *
+ *
+ * @author Apache Software Foundation
* @author Matthew Hawthorne
* @author Gary Gregory
* @since 2.0
@@ -64,9 +45,31 @@
public class IllegalClassException extends IllegalArgumentException {
/**
- * Instantiates with the specified types (classes or interfaces).
+ * Required for serialization support.
*
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = 8063272569377254819L;
+
+ /**
+ * Instantiates with the expected type, and actual object.
+ *
* @param expected the expected type
+ * @param actual the actual object
+ * @since 2.1
+ */
+ public IllegalClassException(Class expected, Object actual) {
+ super(
+ "Expected: "
+ + safeGetClassName(expected)
+ + ", actual: "
+ + (actual == null ? "null" : actual.getClass().getName()));
+ }
+
+ /**
+ * Instantiates with the expected and actual types.
+ *
+ * @param expected the expected type
* @param actual the actual type
*/
public IllegalClassException(Class expected, Class actual) {
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/IncompleteArgumentException.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/IncompleteArgumentException.java (.../IncompleteArgumentException.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/IncompleteArgumentException.java (.../IncompleteArgumentException.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,70 +1,60 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang;
import java.util.Arrays;
/**
- * Thrown to indicate an incomplete argument to a method.
+ * Thrown to indicate an incomplete argument to a method.
+ * This exception supplements the standard IllegalArgumentException
+ * by providing a more semantically rich description of the problem.
*
+ * IncompleteArgumentException
represents the case where a method takes
+ * in a parameter that has a number of properties, some of which have not been set.
+ * A case might be a search requirements bean that must have three properties set
+ * in order for the method to run, but only one is actually set.
+ * This exception would be used in place of
+ * IllegalArgumentException
, yet it still extends it.
+ *
+ *
+ * public void foo(PersonSearcher search) {
+ * if (search.getSurname() == null ||
+ * search.getForename() == null ||
+ * search.getSex() == null) {
+ * throw new IncompleteArgumentException("search");
+ * }
+ * // do something with the searcher
+ * }
+ *
+ *
* @author Matthew Hawthorne
* @since 2.0
* @version $Id$
*/
public class IncompleteArgumentException extends IllegalArgumentException {
/**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = 4954193403612068178L;
+
+ /**
* Instantiates with the specified description.
*
* @param argName a description of the incomplete argument
@@ -87,7 +77,7 @@
}
/**
- * 7Converts an array to a string without throwing an exception.
+ * Converts an array to a string without throwing an exception.
*
* @param array an array
* @return the array as a string
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/IntHashMap.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/IntHashMap.java (.../IntHashMap.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/IntHashMap.java (.../IntHashMap.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,55 +1,18 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
/*
@@ -62,12 +25,12 @@
* A hash map that uses primitive ints for the key rather than objects.
*
* Note that this class is for internal optimization purposes only, and may
- * not be supported in future releases of Jakarta Commons Lang. Utilities of
- * this sort may be included in future releases of Jakarta Commons Collections.
+ * not be supported in future releases of Apache Commons Lang. Utilities of
+ * this sort may be included in future releases of Apache Commons Collections.
*
+ * @author Apache Software Foundation
* @author Justin Couch
* @author Alex Chaffee (alex@apache.org)
- * @author Stephen Colebourne
* @since 2.0
* @version $Revision$
* @see java.util.HashMap
@@ -97,15 +60,15 @@
*
* @serial
*/
- private float loadFactor;
+ private final float loadFactor;
/**
* Innerclass that acts as a datastructure to create a new entry in the
* table.
*/
private static class Entry {
- int hash;
- int key;
+ final int hash;
+ final int key; // TODO not read; seems to be always same as hash
Object value;
Entry next;
@@ -232,6 +195,7 @@
* (which predates the Map interface).
*
* @param value value whose presence in this HashMap is to be tested.
+ * @return boolean true
if the value is contained
* @see java.util.Map
* @since JDK1.2
*/
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/LocaleUtils.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/LocaleUtils.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/LocaleUtils.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,316 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Operations to assist when working with a {@link Locale}.
+ *
+ * This class tries to handle null
input gracefully.
+ * An exception will not be thrown for a null
input.
+ * Each method documents its behaviour in more detail.
+ *
+ * @author Apache Software Foundation
+ * @since 2.2
+ * @version $Id$
+ */
+public class LocaleUtils {
+
+ /** Unmodifiable list of available locales. */
+ private static List cAvailableLocaleList; // lazily created by availableLocaleList()
+
+ /** Unmodifiable set of available locales. */
+ private static Set cAvailableLocaleSet; // lazily created by availableLocaleSet()
+
+ /** Unmodifiable map of language locales by country. */
+ private static final Map cLanguagesByCountry = Collections.synchronizedMap(new HashMap());
+
+ /** Unmodifiable map of country locales by language. */
+ private static final Map cCountriesByLanguage = Collections.synchronizedMap(new HashMap());
+
+ /**
+ * LocaleUtils
instances should NOT be constructed in standard programming.
+ * Instead, the class should be used as LocaleUtils.toLocale("en_GB");
.
+ *
+ * This constructor is public to permit tools that require a JavaBean instance
+ * to operate.
+ */
+ public LocaleUtils() {
+ super();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Converts a String to a Locale.
+ *
+ * This method takes the string format of a locale and creates the
+ * locale object from it.
+ *
+ *
+ * LocaleUtils.toLocale("en") = new Locale("en", "")
+ * LocaleUtils.toLocale("en_GB") = new Locale("en", "GB")
+ * LocaleUtils.toLocale("en_GB_xxx") = new Locale("en", "GB", "xxx") (#)
+ *
+ *
+ * (#) The behaviour of the JDK variant constructor changed between JDK1.3 and JDK1.4.
+ * In JDK1.3, the constructor upper cases the variant, in JDK1.4, it doesn't.
+ * Thus, the result from getVariant() may vary depending on your JDK.
+ *
+ * This method validates the input strictly.
+ * The language code must be lowercase.
+ * The country code must be uppercase.
+ * The separator must be an underscore.
+ * The length must be correct.
+ *
+ *
+ * @param str the locale String to convert, null returns null
+ * @return a Locale, null if null input
+ * @throws IllegalArgumentException if the string is an invalid format
+ */
+ public static Locale toLocale(String str) {
+ if (str == null) {
+ return null;
+ }
+ int len = str.length();
+ if (len != 2 && len != 5 && len < 7) {
+ throw new IllegalArgumentException("Invalid locale format: " + str);
+ }
+ char ch0 = str.charAt(0);
+ char ch1 = str.charAt(1);
+ if (ch0 < 'a' || ch0 > 'z' || ch1 < 'a' || ch1 > 'z') {
+ throw new IllegalArgumentException("Invalid locale format: " + str);
+ }
+ if (len == 2) {
+ return new Locale(str, "");
+ } else {
+ if (str.charAt(2) != '_') {
+ throw new IllegalArgumentException("Invalid locale format: " + str);
+ }
+ char ch3 = str.charAt(3);
+ if (ch3 == '_') {
+ return new Locale(str.substring(0, 2), "", str.substring(4));
+ }
+ char ch4 = str.charAt(4);
+ if (ch3 < 'A' || ch3 > 'Z' || ch4 < 'A' || ch4 > 'Z') {
+ throw new IllegalArgumentException("Invalid locale format: " + str);
+ }
+ if (len == 5) {
+ return new Locale(str.substring(0, 2), str.substring(3, 5));
+ } else {
+ if (str.charAt(5) != '_') {
+ throw new IllegalArgumentException("Invalid locale format: " + str);
+ }
+ return new Locale(str.substring(0, 2), str.substring(3, 5), str.substring(6));
+ }
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Obtains the list of locales to search through when performing
+ * a locale search.
+ *
+ *
+ * localeLookupList(Locale("fr","CA","xxx"))
+ * = [Locale("fr","CA","xxx"), Locale("fr","CA"), Locale("fr")]
+ *
+ *
+ * @param locale the locale to start from
+ * @return the unmodifiable list of Locale objects, 0 being locale, never null
+ */
+ public static List localeLookupList(Locale locale) {
+ return localeLookupList(locale, locale);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Obtains the list of locales to search through when performing
+ * a locale search.
+ *
+ *
+ * localeLookupList(Locale("fr", "CA", "xxx"), Locale("en"))
+ * = [Locale("fr","CA","xxx"), Locale("fr","CA"), Locale("fr"), Locale("en"]
+ *
+ *
+ * The result list begins with the most specific locale, then the
+ * next more general and so on, finishing with the default locale.
+ * The list will never contain the same locale twice.
+ *
+ * @param locale the locale to start from, null returns empty list
+ * @param defaultLocale the default locale to use if no other is found
+ * @return the unmodifiable list of Locale objects, 0 being locale, never null
+ */
+ public static List localeLookupList(Locale locale, Locale defaultLocale) {
+ List list = new ArrayList(4);
+ if (locale != null) {
+ list.add(locale);
+ if (locale.getVariant().length() > 0) {
+ list.add(new Locale(locale.getLanguage(), locale.getCountry()));
+ }
+ if (locale.getCountry().length() > 0) {
+ list.add(new Locale(locale.getLanguage(), ""));
+ }
+ if (list.contains(defaultLocale) == false) {
+ list.add(defaultLocale);
+ }
+ }
+ return Collections.unmodifiableList(list);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Obtains an unmodifiable list of installed locales.
+ *
+ * This method is a wrapper around {@link Locale#getAvailableLocales()}.
+ * It is more efficient, as the JDK method must create a new array each
+ * time it is called.
+ *
+ * @return the unmodifiable list of available locales
+ */
+ public static List availableLocaleList() {
+ if(cAvailableLocaleList == null) {
+ initAvailableLocaleList();
+ }
+ return cAvailableLocaleList;
+ }
+
+ /**
+ * Initializes the availableLocaleList. It is separate from availableLocaleList()
+ * to avoid the synchronized block affecting normal use, yet synchronized and
+ * lazy loading to avoid a static block affecting other methods in this class.
+ */
+ private static synchronized void initAvailableLocaleList() {
+ if(cAvailableLocaleList == null) {
+ List list = Arrays.asList(Locale.getAvailableLocales());
+ cAvailableLocaleList = Collections.unmodifiableList(list);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Obtains an unmodifiable set of installed locales.
+ *
+ * This method is a wrapper around {@link Locale#getAvailableLocales()}.
+ * It is more efficient, as the JDK method must create a new array each
+ * time it is called.
+ *
+ * @return the unmodifiable set of available locales
+ */
+ public static Set availableLocaleSet() {
+ if(cAvailableLocaleSet == null) {
+ initAvailableLocaleSet();
+ }
+ return cAvailableLocaleSet;
+ }
+
+ /**
+ * Initializes the availableLocaleSet. It is separate from availableLocaleSet()
+ * to avoid the synchronized block affecting normal use, yet synchronized and
+ * lazy loading to avoid a static block affecting other methods in this class.
+ */
+ private static synchronized void initAvailableLocaleSet() {
+ if(cAvailableLocaleSet == null) {
+ cAvailableLocaleSet = Collections.unmodifiableSet( new HashSet(availableLocaleList()) );
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Checks if the locale specified is in the list of available locales.
+ *
+ * @param locale the Locale object to check if it is available
+ * @return true if the locale is a known locale
+ */
+ public static boolean isAvailableLocale(Locale locale) {
+ return availableLocaleList().contains(locale);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Obtains the list of languages supported for a given country.
+ *
+ * This method takes a country code and searches to find the
+ * languages available for that country. Variant locales are removed.
+ *
+ * @param countryCode the 2 letter country code, null returns empty
+ * @return an unmodifiable List of Locale objects, never null
+ */
+ public static List languagesByCountry(String countryCode) {
+ List langs = (List) cLanguagesByCountry.get(countryCode); //syncd
+ if (langs == null) {
+ if (countryCode != null) {
+ langs = new ArrayList();
+ List locales = availableLocaleList();
+ for (int i = 0; i < locales.size(); i++) {
+ Locale locale = (Locale) locales.get(i);
+ if (countryCode.equals(locale.getCountry()) &&
+ locale.getVariant().length() == 0) {
+ langs.add(locale);
+ }
+ }
+ langs = Collections.unmodifiableList(langs);
+ } else {
+ langs = Collections.EMPTY_LIST;
+ }
+ cLanguagesByCountry.put(countryCode, langs); //syncd
+ }
+ return langs;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Obtains the list of countries supported for a given language.
+ *
+ * This method takes a language code and searches to find the
+ * countries available for that language. Variant locales are removed.
+ *
+ * @param languageCode the 2 letter language code, null returns empty
+ * @return an unmodifiable List of Locale objects, never null
+ */
+ public static List countriesByLanguage(String languageCode) {
+ List countries = (List) cCountriesByLanguage.get(languageCode); //syncd
+ if (countries == null) {
+ if (languageCode != null) {
+ countries = new ArrayList();
+ List locales = availableLocaleList();
+ for (int i = 0; i < locales.size(); i++) {
+ Locale locale = (Locale) locales.get(i);
+ if (languageCode.equals(locale.getLanguage()) &&
+ locale.getCountry().length() != 0 &&
+ locale.getVariant().length() == 0) {
+ countries.add(locale);
+ }
+ }
+ countries = Collections.unmodifiableList(countries);
+ } else {
+ countries = Collections.EMPTY_LIST;
+ }
+ cCountriesByLanguage.put(languageCode, countries); //syncd
+ }
+ return countries;
+ }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/NotImplementedException.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/NotImplementedException.java (.../NotImplementedException.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/NotImplementedException.java (.../NotImplementedException.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,85 +1,295 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+import org.apache.commons.lang.exception.Nestable;
+import org.apache.commons.lang.exception.NestableDelegate;
+
/**
- * Thrown to indicate that a method has not been implemented.
+ * Thrown to indicate that a block of code has not been implemented.
+ * This exception supplements UnsupportedOperationException
+ * by providing a more semantically rich description of the problem.
*
+ * NotImplementedException
represents the case where the
+ * author has yet to implement the logic at this point in the program.
+ * This can act as an exception based TODO tag.
+ * Because this logic might be within a catch block, this exception
+ * suports exception chaining.
+ *
+ *
+ * public void foo() {
+ * try {
+ * // do something that throws an Exception
+ * } catch (Exception ex) {
+ * // don't know what to do here yet
+ * throw new NotImplementedException("TODO", ex);
+ * }
+ * }
+ *
+ *
+ * @author Apache Software Foundation
* @author Matthew Hawthorne
* @since 2.0
* @version $Id$
*/
-public class NotImplementedException extends UnsupportedOperationException {
+public class NotImplementedException
+ extends UnsupportedOperationException implements Nestable {
+ private static final String DEFAULT_MESSAGE = "Code is not implemented";
+
/**
- * Constructes the exception with the specified class.
+ * Required for serialization support.
*
- * @param clazz the Class
that has not implemented the method
+ * @see java.io.Serializable
*/
+ private static final long serialVersionUID = -6894122266938754088L;
+
+ /**
+ * The exception helper to delegate nested exception handling to.
+ */
+ private NestableDelegate delegate = new NestableDelegate(this);
+
+ /**
+ * Holds the reference to the exception or error that caused
+ * this exception to be thrown.
+ */
+ private Throwable cause;
+
+ //-----------------------------------------------------------------------
+ /**
+ * Constructs a new NotImplementedException
with default message.
+ *
+ * @since 2.1
+ */
+ public NotImplementedException() {
+ super(DEFAULT_MESSAGE);
+ }
+
+ /**
+ * Constructs a new NotImplementedException
with specified
+ * detail message.
+ *
+ * @param msg the error message.
+ */
+ public NotImplementedException(String msg) {
+ super(msg == null ? DEFAULT_MESSAGE : msg);
+ }
+
+ /**
+ * Constructs a new NotImplementedException
with specified
+ * nested Throwable
and default message.
+ *
+ * @param cause the exception that caused this exception to be thrown
+ * @since 2.1
+ */
+ public NotImplementedException(Throwable cause) {
+ super(DEFAULT_MESSAGE);
+ this.cause = cause;
+ }
+
+ /**
+ * Constructs a new NotImplementedException
with specified
+ * detail message and nested Throwable
.
+ *
+ * @param msg the error message
+ * @param cause the exception that caused this exception to be thrown
+ * @since 2.1
+ */
+ public NotImplementedException(String msg, Throwable cause) {
+ super(msg == null ? DEFAULT_MESSAGE : msg);
+ this.cause = cause;
+ }
+
+ /**
+ * Constructs a new NotImplementedException
referencing the specified class.
+ *
+ * @param clazz
+ * the Class
that has not implemented the method
+ */
public NotImplementedException(Class clazz) {
- super(
- "Method is not implemented in class "
- + ((clazz == null) ? null : clazz.getName()));
+ super(clazz == null ? DEFAULT_MESSAGE : DEFAULT_MESSAGE + " in " + clazz);
}
+ // -----------------------------------------------------------------------
/**
- * Constructs the exception with the specified message.
+ * Gets the root cause of this exception.
+ * @return the root cause of this exception.
*
- * @param msg the exception message.
+ * @since 2.1
*/
- public NotImplementedException(String msg) {
- super(msg);
+ public Throwable getCause() {
+ return cause;
}
+ /**
+ * Gets the combined the error message of this and any nested errors.
+ *
+ * @return the error message
+ * @since 2.1
+ */
+ public String getMessage() {
+ if (super.getMessage() != null) {
+ return super.getMessage();
+ } else if (cause != null) {
+ return cause.toString();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the error message of the Throwable
in the chain
+ * of Throwable
s at the specified index, numbered from 0.
+ *
+ * @param index the index of the Throwable
in the chain
+ * @return the error message, or null if the Throwable
at the
+ * specified index in the chain does not contain a message
+ * @throws IndexOutOfBoundsException if the index
argument is
+ * negative or not less than the count of Throwable
s in the chain
+ * @since 2.1
+ */
+ public String getMessage(int index) {
+ if (index == 0) {
+ return super.getMessage();
+ }
+ return delegate.getMessage(index);
+ }
+
+ /**
+ * Returns the error message of this and any nested Throwable
objects.
+ * Each throwable returns a message, a null string is included in the array if
+ * there is no message for a particular Throwable
.
+ *
+ * @return the error messages
+ * @since 2.1
+ */
+ public String[] getMessages() {
+ return delegate.getMessages();
+ }
+
+ /**
+ * Returns the Throwable
in the chain by index.
+ *
+ * @param index the index to retrieve
+ * @return the Throwable
+ * @throws IndexOutOfBoundsException if the index
argument is
+ * negative or not less than the count of Throwable
s in the chain
+ * @since 2.1
+ */
+ public Throwable getThrowable(int index) {
+ return delegate.getThrowable(index);
+ }
+
+ /**
+ * Returns the number of nested Throwable
s represented by
+ * this Nestable
, including this Nestable
.
+ *
+ * @return the throwable count
+ * @since 2.1
+ */
+ public int getThrowableCount() {
+ return delegate.getThrowableCount();
+ }
+
+ /**
+ * Returns this Nestable
and any nested Throwable
s
+ * in an array of Throwable
s, one element for each
+ * Throwable
.
+ *
+ * @return the Throwable
s
+ * @since 2.1
+ */
+ public Throwable[] getThrowables() {
+ return delegate.getThrowables();
+ }
+
+ /**
+ * Returns the index of the first occurrence of the specified type.
+ * If there is no match, -1
is returned.
+ *
+ * @param type the type to search for
+ * @return index of the first occurrence of the type in the chain, or -1 if
+ * the type is not found
+ * @since 2.1
+ */
+ public int indexOfThrowable(Class type) {
+ return delegate.indexOfThrowable(type, 0);
+ }
+
+ /**
+ * Returns the index of the first occurrence of the specified type starting
+ * from the specified index. If there is no match, -1
is returned.
+ *
+ * @param type the type to search for
+ * @param fromIndex the index of the starting position in the chain to be searched
+ * @return index of the first occurrence of the type in the chain, or -1 if
+ * the type is not found
+ * @throws IndexOutOfBoundsException if the fromIndex
argument
+ * is negative or not less than the count of Throwable
s in the chain
+ * @since 2.1
+ */
+ public int indexOfThrowable(Class type, int fromIndex) {
+ return delegate.indexOfThrowable(type, fromIndex);
+ }
+
+ /**
+ * Prints the stack trace of this exception.
+ * Includes information from the exception, if any, which caused this exception.
+ *
+ * @since 2.1
+ */
+ public void printStackTrace() {
+ delegate.printStackTrace();
+ }
+
+ /**
+ * Prints the stack trace of this exception to the specified stream.
+ * Includes information from the exception, if any, which caused this exception.
+ *
+ * @param out the stream to write to
+ * @since 2.1
+ */
+ public void printStackTrace(PrintStream out) {
+ delegate.printStackTrace(out);
+ }
+
+ /**
+ * Prints the stack trace of this exception to the specified writer.
+ * Includes information from the exception, if any, which caused this exception.
+ *
+ * @param out the writer to write to
+ * @since 2.1
+ */
+ public void printStackTrace(PrintWriter out) {
+ delegate.printStackTrace(out);
+ }
+
+ /**
+ * Prints the stack trace for this exception only (root cause not included)
+ * using the specified writer.
+ *
+ * @param out the writer to write to
+ * @since 2.1
+ */
+ public final void printPartialStackTrace(PrintWriter out) {
+ super.printStackTrace(out);
+ }
+
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/NullArgumentException.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/NullArgumentException.java (.../NullArgumentException.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/NullArgumentException.java (.../NullArgumentException.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,76 +1,64 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang;
/**
* Thrown to indicate that an argument was null
and should
- * not have been.
+ * not have been.
+ * This exception supplements the standard IllegalArgumentException
+ * by providing a more semantically rich description of the problem.
*
+ * NullArgumentException
represents the case where a method takes
+ * in a parameter that must not be null
.
+ * Some coding standards would use NullPointerException
for this case,
+ * others will use IllegalArgumentException
.
+ * Thus this exception would be used in place of
+ * IllegalArgumentException
, yet it still extends it.
+ *
+ *
+ * public void foo(String str) {
+ * if (str == null) {
+ * throw new NullArgumentException("str");
+ * }
+ * // do something with the string
+ * }
+ *
+ *
+ * @author Apache Software Foundation
* @author Matthew Hawthorne
- * @author Stephen Colebourne
* @since 2.0
* @version $Id$
*/
public class NullArgumentException extends IllegalArgumentException {
- /**
- * Instantiates with the given argument name.
+ /**
+ * Required for serialization support.
*
- * @param argName the name of the argument that was null
.
- */
- public NullArgumentException(String argName) {
- super(argName + " must not be null.");
- }
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = 1174360235354917591L;
+ /**
+ * Instantiates with the given argument name.
+ *
+ * @param argName the name of the argument that was null
.
+ */
+ public NullArgumentException(String argName) {
+ super((argName == null ? "Argument" : argName) + " must not be null.");
+ }
+
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/NumberRange.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/NumberRange.java (.../NumberRange.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/NumberRange.java (.../NumberRange.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,67 +1,32 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang;
+import org.apache.commons.lang.text.StrBuilder;
+
/**
* Represents a range of {@link Number} objects.
*
* This class uses double
comparisons. This means that it
* is unsuitable for dealing with large Long
, BigDecimal
* or BigInteger
numbers.
*
+ * @author Apache Software Foundation
* @author Christopher Elkins
- * @author Stephen Colebourne
* @since 1.0
* @version $Revision$ $Date$
*
@@ -231,7 +196,7 @@
* @return the string representation of this range
*/
public String toString() {
- StringBuffer sb = new StringBuffer();
+ StrBuilder sb = new StrBuilder();
if (min.doubleValue() < 0) {
sb.append('(')
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/NumberUtils.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/NumberUtils.java (.../NumberUtils.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/NumberUtils.java (.../NumberUtils.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,55 +1,18 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang;
@@ -59,9 +22,8 @@
/**
* Provides extra functionality for Java Number classes.
*
- * @author Henri Yandell
+ * @author Apache Software Foundation
* @author Rand McNeely
- * @author Stephen Colebourne
* @author Steve Downey
* @author Eric Pugh
* @author Phil Steitz
@@ -82,6 +44,7 @@
* to operate.
*/
public NumberUtils() {
+ super();
}
//--------------------------------------------------------------------
@@ -156,7 +119,7 @@
*
* First, the value is examined for a type qualifier on the end
* ('f','F','d','D','l','L'
). If it is found, it starts
- * trying to create succissively larger types from the type specified
+ * trying to create successively larger types from the type specified
* until one is found that can hold the value.
*
* If a type specifier is not found, it will check for a decimal point
@@ -179,6 +142,9 @@
if (val.length() == 0) {
throw new NumberFormatException("\"\" is not a valid number.");
}
+ if (val.length() == 1 && !Character.isDigit(val.charAt(0))) {
+ throw new NumberFormatException(val + " is not a valid number.");
+ }
if (val.startsWith("--")) {
// this is protection for poorness in java.lang.BigDecimal.
// it accepts this as a legal value, but it does not appear
@@ -229,8 +195,7 @@
case 'L' :
if (dec == null
&& exp == null
- && isDigits(numeric.substring(1))
- && (numeric.charAt(0) == '-' || Character.isDigit(numeric.charAt(0)))) {
+ && (numeric.charAt(0) == '-' && isDigits(numeric.substring(1)) || isDigits(numeric))) {
try {
return createLong(numeric);
} catch (NumberFormatException nfe) {
@@ -246,13 +211,14 @@
Float f = NumberUtils.createFloat(numeric);
if (!(f.isInfinite() || (f.floatValue() == 0.0F && !allZeros))) {
//If it's too big for a float or the float value = 0 and the string
- //has non-zeros in it, then float doens't have the presision we want
+ //has non-zeros in it, then float does not have the precision we want
return f;
}
- } catch (NumberFormatException nfe) {
+ } catch (NumberFormatException e) {
+ // ignore the bad number
}
- //Fall through
+ //$FALL-THROUGH$
case 'd' :
case 'D' :
try {
@@ -261,12 +227,14 @@
return d;
}
} catch (NumberFormatException nfe) {
+ // empty catch
}
try {
return createBigDecimal(numeric);
} catch (NumberFormatException e) {
+ // empty catch
}
- //Fall through
+ //$FALL-THROUGH$
default :
throw new NumberFormatException(val + " is not a valid number.");
@@ -284,10 +252,12 @@
try {
return createInteger(val);
} catch (NumberFormatException nfe) {
+ // empty catch
}
try {
return createLong(val);
} catch (NumberFormatException nfe) {
+ // empty catch
}
return createBigInteger(val);
@@ -300,13 +270,15 @@
return f;
}
} catch (NumberFormatException nfe) {
+ // empty catch
}
try {
Double d = createDouble(val);
if (!(d.isInfinite() || (d.doubleValue() == 0.0D && !allZeros))) {
return d;
}
} catch (NumberFormatException nfe) {
+ // empty catch
}
return createBigDecimal(val);
@@ -501,7 +473,7 @@
*
NaN
* Positive infinity
* Maximum double
- * Normal positve numbers
+ * Normal positive numbers
* +0.0
* -0.0
* Normal negative numbers
@@ -550,7 +522,7 @@
/**
* Compares two floats for order.
*
- * This method is more comprhensive than the standard Java greater than,
+ *
This method is more comprehensive than the standard Java greater than,
* less than and equals operators.
*
* - It returns
-1
if the first value is less than the second.
@@ -563,7 +535,7 @@
* - NaN
*
- Positive infinity
*
- Maximum float
- *
- Normal positve numbers
+ *
- Normal positive numbers
*
- +0.0
*
- -0.0
*
- Normal negative numbers
@@ -646,7 +618,7 @@
* @return
true
if the string is a correctly formatted number
*/
public static boolean isNumber(String str) {
- if ((str == null) || (str.length() == 0)) {
+ if (StringUtils.isEmpty(str)) {
return false;
}
char[] chars = str.toCharArray();
@@ -730,7 +702,7 @@
}
if (chars[i] == 'l'
|| chars[i] == 'L') {
- // not allowing L with an exponoent
+ // not allowing L with an exponent
return foundDigit && !hasExp;
}
// last character is illegal
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/ObjectUtils.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/ObjectUtils.java (.../ObjectUtils.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/ObjectUtils.java (.../ObjectUtils.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,77 +1,49 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang;
import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import org.apache.commons.lang.exception.CloneFailedException;
+import org.apache.commons.lang.reflect.MethodUtils;
+
/**
* Operations on Object
.
*
* This class tries to handle null
input gracefully.
* An exception will generally not be thrown for a null
input.
* Each method documents its behaviour in more detail.
*
+ * #ThreadSafe#
+ * @author Apache Software Foundation
* @author Nissim Karpenstein
* @author Janek Bogucki
- * @author Daniel Rall
- * @author Stephen Colebourne
+ * @author Daniel L. Rall
* @author Gary Gregory
+ * @author Mario Winterer
+ * @author David J. M. Karlsen
* @since 1.0
* @version $Id$
*/
+//@Immutable
public class ObjectUtils {
-
+
/**
* Singleton used as a null
placeholder where
* null
has another meaning.
@@ -99,6 +71,7 @@
* to operate.
*/
public ObjectUtils() {
+ super();
}
// Defaulting
@@ -120,7 +93,7 @@
* @return object
if it is not null
, defaultValue otherwise
*/
public static Object defaultIfNull(Object object, Object defaultValue) {
- return (object != null ? object : defaultValue);
+ return object != null ? object : defaultValue;
}
/**
@@ -151,7 +124,48 @@
}
return object1.equals(object2);
}
-
+
+ /**
+ * Compares two objects for inequality, where either one or both
+ * objects may be null
.
+ *
+ *
+ * ObjectUtils.notEqual(null, null) = false
+ * ObjectUtils.notEqual(null, "") = true
+ * ObjectUtils.notEqual("", null) = true
+ * ObjectUtils.notEqual("", "") = false
+ * ObjectUtils.notEqual(Boolean.TRUE, null) = true
+ * ObjectUtils.notEqual(Boolean.TRUE, "true") = true
+ * ObjectUtils.notEqual(Boolean.TRUE, Boolean.TRUE) = false
+ * ObjectUtils.notEqual(Boolean.TRUE, Boolean.FALSE) = true
+ *
+ *
+ * @param object1 the first object, may be null
+ * @param object2 the second object, may be null
+ * @return false
if the values of both objects are the same
+ * @since 2.6
+ */
+ public static boolean notEqual(Object object1, Object object2) {
+ return ObjectUtils.equals(object1, object2) == false;
+ }
+
+ /**
+ * Gets the hash code of an object returning zero when the
+ * object is null
.
+ *
+ *
+ * ObjectUtils.hashCode(null) = 0
+ * ObjectUtils.hashCode(obj) = obj.hashCode()
+ *
+ *
+ * @param obj the object to obtain the hash code of, may be null
+ * @return the hash code of the object, or zero if null
+ * @since 2.1
+ */
+ public static int hashCode(Object obj) {
+ return (obj == null) ? 0 : obj.hashCode();
+ }
+
// Identity ToString
//-----------------------------------------------------------------------
/**
@@ -174,12 +188,38 @@
if (object == null) {
return null;
}
- return appendIdentityToString(null, object).toString();
+ StringBuffer buffer = new StringBuffer();
+ identityToString(buffer, object);
+ return buffer.toString();
}
/**
* Appends the toString that would be produced by Object
* if a class did not override toString itself. null
+ * will throw a NullPointerException for either of the two parameters.
+ *
+ *
+ * ObjectUtils.identityToString(buf, "") = buf.append("java.lang.String@1e23"
+ * ObjectUtils.identityToString(buf, Boolean.TRUE) = buf.append("java.lang.Boolean@7fa"
+ * ObjectUtils.identityToString(buf, Boolean.TRUE) = buf.append("java.lang.Boolean@7fa")
+ *
+ *
+ * @param buffer the buffer to append to
+ * @param object the object to create a toString for
+ * @since 2.4
+ */
+ public static void identityToString(StringBuffer buffer, Object object) {
+ if (object == null) {
+ throw new NullPointerException("Cannot get the toString of a null identity");
+ }
+ buffer.append(object.getClass().getName())
+ .append('@')
+ .append(Integer.toHexString(System.identityHashCode(object)));
+ }
+
+ /**
+ * Appends the toString that would be produced by Object
+ * if a class did not override toString itself. null
* will return null
.
*
*
@@ -194,6 +234,7 @@
* @return the default toString text, or null
if
* null
passed in
* @since 2.0
+ * @deprecated The design of this method is bad - see LANG-360. Instead, use identityToString(StringBuffer, Object).
*/
public static StringBuffer appendIdentityToString(StringBuffer buffer, Object object) {
if (object == null) {
@@ -228,7 +269,7 @@
* @since 2.0
*/
public static String toString(Object obj) {
- return (obj == null ? "" : obj.toString());
+ return obj == null ? "" : obj.toString();
}
/**
@@ -251,9 +292,144 @@
* @since 2.0
*/
public static String toString(Object obj, String nullStr) {
- return (obj == null ? nullStr : obj.toString());
+ return obj == null ? nullStr : obj.toString();
}
+ // Min/Max
+ //-----------------------------------------------------------------------
+ /**
+ * Null safe comparison of Comparables.
+ *
+ * @param c1 the first comparable, may be null
+ * @param c2 the second comparable, may be null
+ * @return
+ *
+ * - If both objects are non-null and unequal, the lesser object.
+ *
- If both objects are non-null and equal, c1.
+ *
- If one of the comparables is null, the non-null object.
+ *
- If both the comparables are null, null is returned.
+ *
+ */
+ public static Object min(Comparable c1, Comparable c2) {
+ return (compare(c1, c2, true) <= 0 ? c1 : c2);
+ }
+
+ /**
+ * Null safe comparison of Comparables.
+ *
+ * @param c1 the first comparable, may be null
+ * @param c2 the second comparable, may be null
+ * @return
+ *
+ * - If both objects are non-null and unequal, the greater object.
+ *
- If both objects are non-null and equal, c1.
+ *
- If one of the comparables is null, the non-null object.
+ *
- If both the comparables are null, null is returned.
+ *
+ */
+ public static Object max(Comparable c1, Comparable c2) {
+ return (compare(c1, c2, false) >= 0 ? c1 : c2);
+ }
+
+ /**
+ * Null safe comparison of Comparables.
+ * {@code null} is assumed to be less than a non-{@code null} value.
+ *
+ * @param c1 the first comparable, may be null
+ * @param c2 the second comparable, may be null
+ * @return a negative value if c1 < c2, zero if c1 = c2
+ * and a positive value if c1 > c2
+ * @since 2.6
+ */
+ public static int compare(Comparable c1, Comparable c2) {
+ return compare(c1, c2, false);
+ }
+
+ /**
+ * Null safe comparison of Comparables.
+ *
+ * @param c1 the first comparable, may be null
+ * @param c2 the second comparable, may be null
+ * @param nullGreater if true null
is considered greater
+ * than a Non-null
value or if false null
is
+ * considered less than a Non-null
value
+ * @return a negative value if c1 < c2, zero if c1 = c2
+ * and a positive value if c1 > c2
+ * @see java.util.Comparator#compare(Object, Object)
+ * @since 2.6
+ */
+ public static int compare(Comparable c1, Comparable c2, boolean nullGreater) {
+ if (c1 == c2) {
+ return 0;
+ } else if (c1 == null) {
+ return (nullGreater ? 1 : -1);
+ } else if (c2 == null) {
+ return (nullGreater ? -1 : 1);
+ }
+ return c1.compareTo(c2);
+ }
+
+ /**
+ * Clone an object.
+ *
+ * @param o the object to clone
+ * @return the clone if the object implements {@link Cloneable} otherwise null
+ * @throws CloneFailedException if the object is cloneable and the clone operation fails
+ * @since 2.6
+ */
+ public static Object clone(final Object o) {
+ if (o instanceof Cloneable) {
+ final Object result;
+ if (o.getClass().isArray()) {
+ final Class componentType = o.getClass().getComponentType();
+ if (!componentType.isPrimitive()) {
+ result = ((Object[])o).clone();
+ } else {
+ int length = Array.getLength(o);
+ result = Array.newInstance(componentType, length);
+ while (length-- > 0) {
+ Array.set(result, length, Array.get(o, length));
+ }
+ }
+ } else {
+ try {
+ result = MethodUtils.invokeMethod(o, "clone", null);
+ } catch (final NoSuchMethodException e) {
+ throw new CloneFailedException("Cloneable type "
+ + o.getClass().getName()
+ + " has no clone method", e);
+ } catch (final IllegalAccessException e) {
+ throw new CloneFailedException("Cannot clone Cloneable type "
+ + o.getClass().getName(), e);
+ } catch (final InvocationTargetException e) {
+ throw new CloneFailedException("Exception cloning Cloneable type "
+ + o.getClass().getName(), e.getTargetException());
+ }
+ }
+ return result;
+ }
+
+ return null;
+ }
+
+ /**
+ * Clone an object if possible. This method is similar to {@link #clone(Object)}, but will
+ * return the provided instance as the return value instead of null
if the instance
+ * is not cloneable. This is more convenient if the caller uses different
+ * implementations (e.g. of a service) and some of the implementations do not allow concurrent
+ * processing or have state. In such cases the implementation can simply provide a proper
+ * clone implementation and the caller's code does not have to change.
+ *
+ * @param o the object to clone
+ * @return the clone if the object implements {@link Cloneable} otherwise the object itself
+ * @throws CloneFailedException if the object is cloneable and the clone operation fails
+ * @since 2.6
+ */
+ public static Object cloneIfPossible(final Object o) {
+ final Object clone = clone(o);
+ return clone == null ? o : clone;
+ }
+
// Null
//-----------------------------------------------------------------------
/**
@@ -271,13 +447,18 @@
* cannot be stored.
*/
public static class Null implements Serializable {
- // declare serialization compatability with Commons Lang 1.0
+ /**
+ * Required for serialization support. Declare serialization compatibility with Commons Lang 1.0
+ *
+ * @see java.io.Serializable
+ */
private static final long serialVersionUID = 7092611880189329093L;
/**
* Restricted constructor - singleton.
*/
Null() {
+ super();
}
/**
@@ -289,5 +470,5 @@
return ObjectUtils.NULL;
}
}
-
+
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/RandomStringUtils.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/RandomStringUtils.java (.../RandomStringUtils.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/RandomStringUtils.java (.../RandomStringUtils.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,66 +1,36 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang;
import java.util.Random;
/**
* Operations for random String
s.
+ * Currently private high surrogate characters are ignored.
+ * These are unicode characters that fall between the values 56192 (db80)
+ * and 56319 (dbff) as we don't know how to handle them.
+ * High and low surrogates are correctly dealt with - that is if a
+ * high surrogate is randomly chosen, 55296 (d800) to 56191 (db7f)
+ * then it is followed by a low surrogate. If a low surrogate is chosen,
+ * 56320 (dc00) to 57343 (dfff) then it is placed after a randomly
+ * chosen high surrogate.
*
- * @author GenerationJava Core library
- * @author Henri Yandell
+ * #ThreadSafe#
+ * @author Apache Software Foundation
* @author Steven Caswell
- * @author Stephen Colebourne
* @author Gary Gregory
* @author Phil Steitz
* @since 1.0
@@ -84,6 +54,7 @@
* to operate.
*/
public RandomStringUtils() {
+ super();
}
// Random
@@ -167,7 +138,7 @@
* @param count the length of random string to create
* @param letters if true
, generated string will include
* alphabetic characters
- * @param numbers if true
, generatd string will include
+ * @param numbers if true
, generated string will include
* numeric characters
* @return the random string
*/
@@ -252,7 +223,8 @@
* @throws IllegalArgumentException if count
< 0.
* @since 2.0
*/
- public static String random(int count, int start, int end, boolean letters, boolean numbers, char[] chars, Random random) {
+ public static String random(int count, int start, int end, boolean letters, boolean numbers,
+ char[] chars, Random random) {
if (count == 0) {
return "";
} else if (count < 0) {
@@ -267,7 +239,7 @@
}
}
- StringBuffer buffer = new StringBuffer();
+ char[] buffer = new char[count];
int gap = end - start;
while (count-- != 0) {
@@ -277,16 +249,39 @@
} else {
ch = chars[random.nextInt(gap) + start];
}
- if ((letters && numbers && Character.isLetterOrDigit(ch))
- || (letters && Character.isLetter(ch))
+ if ((letters && Character.isLetter(ch))
|| (numbers && Character.isDigit(ch))
- || (!letters && !numbers)) {
- buffer.append(ch);
+ || (!letters && !numbers))
+ {
+ if(ch >= 56320 && ch <= 57343) {
+ if(count == 0) {
+ count++;
+ } else {
+ // low surrogate, insert high surrogate after putting it in
+ buffer[count] = ch;
+ count--;
+ buffer[count] = (char) (55296 + random.nextInt(128));
+ }
+ } else if(ch >= 55296 && ch <= 56191) {
+ if(count == 0) {
+ count++;
+ } else {
+ // high surrogate, insert low surrogate before putting it in
+ buffer[count] = (char) (56320 + random.nextInt(128));
+ count--;
+ buffer[count] = ch;
+ }
+ } else if(ch >= 56192 && ch <= 56319) {
+ // private high surrogate, no effing clue, so skip it
+ count++;
+ } else {
+ buffer[count] = ch;
+ }
} else {
count++;
}
}
- return buffer.toString();
+ return new String(buffer);
}
/**
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/SerializationException.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/SerializationException.java (.../SerializationException.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/SerializationException.java (.../SerializationException.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,55 +1,18 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang;
@@ -60,13 +23,20 @@
*
* The original error is wrapped within this one.
*
- * @author Stephen Colebourne
+ * @author Apache Software Foundation
* @since 1.0
* @version $Id$
*/
public class SerializationException extends NestableRuntimeException {
/**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = 4029025366392702726L;
+
+ /**
* Constructs a new SerializationException
without specified
* detail message.
*/
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/SerializationUtils.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/SerializationUtils.java (.../SerializationUtils.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/SerializationUtils.java (.../SerializationUtils.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,55 +1,18 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang;
@@ -75,10 +38,11 @@
* This class throws exceptions for invalid null
inputs.
* Each method documents its behaviour in more detail.
*
+ * #ThreadSafe#
+ * @author Apache Software Foundation
* @author Nissim Karpenstein
* @author Janek Bogucki
- * @author Daniel Rall
- * @author Stephen Colebourne
+ * @author Daniel L. Rall
* @author Jeff Varszegi
* @author Gary Gregory
* @since 1.0
@@ -152,7 +116,7 @@
out.close();
}
} catch (IOException ex) {
- // ignore;
+ // ignore close exception
}
}
}
@@ -208,7 +172,7 @@
in.close();
}
} catch (IOException ex) {
- // ignore
+ // ignore close exception
}
}
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/StringEscapeUtils.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/StringEscapeUtils.java (.../StringEscapeUtils.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/StringEscapeUtils.java (.../StringEscapeUtils.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,73 +1,39 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang;
import java.io.IOException;
+import java.io.StringWriter;
import java.io.Writer;
+import java.util.Locale;
import org.apache.commons.lang.exception.NestableRuntimeException;
+import org.apache.commons.lang.text.StrBuilder;
/**
* Escapes and unescapes String
s for
* Java, Java Script, HTML, XML, and SQL.
*
+ * #ThreadSafe#
+ * @author Apache Software Foundation
* @author Apache Jakarta Turbine
- * @author GenerationJavaCore library
* @author Purple Technology
- * @author Henri Yandell
* @author Alexander Day Chaffee
- * @author Antony Riley
+ * @author Antony Riley
* @author Helge Tesgaard
* @author Sean Brown
* @author Gary Gregory
@@ -78,6 +44,11 @@
*/
public class StringEscapeUtils {
+ private static final char CSV_DELIMITER = ',';
+ private static final char CSV_QUOTE = '"';
+ private static final String CSV_QUOTE_STR = String.valueOf(CSV_QUOTE);
+ private static final char[] CSV_SEARCH_CHARS = new char[] {CSV_DELIMITER, CSV_QUOTE, CharUtils.CR, CharUtils.LF};
+
/**
* StringEscapeUtils
instances should NOT be constructed in
* standard programming.
@@ -89,6 +60,7 @@
* instance to operate.
*/
public StringEscapeUtils() {
+ super();
}
// Java and JavaScript
@@ -115,7 +87,7 @@
* @return String with escaped values, null
if null string input
*/
public static String escapeJava(String str) {
- return escapeJavaStyleString(str, false);
+ return escapeJavaStyleString(str, false, false);
}
/**
@@ -128,10 +100,10 @@
* @param out Writer to write escaped string into
* @param str String to escape values in, may be null
* @throws IllegalArgumentException if the Writer is null
- * @throws IOException if error occurs on undelying Writer
+ * @throws IOException if error occurs on underlying Writer
*/
public static void escapeJava(Writer out, String str) throws IOException {
- escapeJavaStyleString(out, str, false);
+ escapeJavaStyleString(out, str, false, false);
}
/**
@@ -156,7 +128,7 @@
* @return String with escaped values, null
if null string input
*/
public static String escapeJavaScript(String str) {
- return escapeJavaStyleString(str, true);
+ return escapeJavaStyleString(str, true, true);
}
/**
@@ -169,28 +141,45 @@
* @param out Writer to write escaped string into
* @param str String to escape values in, may be null
* @throws IllegalArgumentException if the Writer is null
- * @throws IOException if error occurs on undelying Writer
+ * @throws IOException if error occurs on underlying Writer
**/
public static void escapeJavaScript(Writer out, String str) throws IOException {
- escapeJavaStyleString(out, str, true);
+ escapeJavaStyleString(out, str, true, true);
}
- private static String escapeJavaStyleString(String str, boolean escapeSingleQuotes) {
+ /**
+ * Worker method for the {@link #escapeJavaScript(String)} method.
+ *
+ * @param str String to escape values in, may be null
+ * @param escapeSingleQuotes escapes single quotes if true
+ * @param escapeForwardSlash TODO
+ * @return the escaped string
+ */
+ private static String escapeJavaStyleString(String str, boolean escapeSingleQuotes, boolean escapeForwardSlash) {
if (str == null) {
return null;
}
try {
- StringPrintWriter writer = new StringPrintWriter(str.length() * 2);
- escapeJavaStyleString(writer, str, escapeSingleQuotes);
- return writer.getString();
+ StringWriter writer = new StringWriter(str.length() * 2);
+ escapeJavaStyleString(writer, str, escapeSingleQuotes, escapeForwardSlash);
+ return writer.toString();
} catch (IOException ioe) {
// this should never ever happen while writing to a StringWriter
- ioe.printStackTrace();
- return null;
+ throw new UnhandledException(ioe);
}
}
- private static void escapeJavaStyleString(Writer out, String str, boolean escapeSingleQuote) throws IOException {
+ /**
+ * Worker method for the {@link #escapeJavaScript(String)} method.
+ *
+ * @param out write to receieve the escaped string
+ * @param str String to escape values in, may be null
+ * @param escapeSingleQuote escapes single quotes if true
+ * @param escapeForwardSlash TODO
+ * @throws IOException if an IOException occurs
+ */
+ private static void escapeJavaStyleString(Writer out, String str, boolean escapeSingleQuote,
+ boolean escapeForwardSlash) throws IOException {
if (out == null) {
throw new IllegalArgumentException("The Writer must not be null");
}
@@ -211,23 +200,23 @@
out.write("\\u00" + hex(ch));
} else if (ch < 32) {
switch (ch) {
- case '\b':
+ case '\b' :
out.write('\\');
out.write('b');
break;
- case '\n':
+ case '\n' :
out.write('\\');
out.write('n');
break;
- case '\t':
+ case '\t' :
out.write('\\');
out.write('t');
break;
- case '\f':
+ case '\f' :
out.write('\\');
out.write('f');
break;
- case '\r':
+ case '\r' :
out.write('\\');
out.write('r');
break;
@@ -241,18 +230,26 @@
}
} else {
switch (ch) {
- case '\'':
- if (escapeSingleQuote) out.write('\\');
+ case '\'' :
+ if (escapeSingleQuote) {
+ out.write('\\');
+ }
out.write('\'');
break;
- case '"':
+ case '"' :
out.write('\\');
out.write('"');
break;
- case '\\':
+ case '\\' :
out.write('\\');
out.write('\\');
break;
+ case '/' :
+ if (escapeForwardSlash) {
+ out.write('\\');
+ }
+ out.write('/');
+ break;
default :
out.write(ch);
break;
@@ -269,7 +266,7 @@
* @return An upper case hexadecimal String
*/
private static String hex(char ch) {
- return Integer.toHexString(ch).toUpperCase();
+ return Integer.toHexString(ch).toUpperCase(Locale.ENGLISH);
}
/**
@@ -286,13 +283,12 @@
return null;
}
try {
- StringPrintWriter writer = new StringPrintWriter(str.length());
+ StringWriter writer = new StringWriter(str.length());
unescapeJava(writer, str);
- return writer.getString();
+ return writer.toString();
} catch (IOException ioe) {
// this should never ever happen while writing to a StringWriter
- ioe.printStackTrace();
- return null;
+ throw new UnhandledException(ioe);
}
}
@@ -309,7 +305,7 @@
* @param out the Writer
used to output unescaped characters
* @param str the String
to unescape, may be null
* @throws IllegalArgumentException if the Writer is null
- * @throws IOException if error occurs on undelying Writer
+ * @throws IOException if error occurs on underlying Writer
*/
public static void unescapeJava(Writer out, String str) throws IOException {
if (out == null) {
@@ -319,7 +315,7 @@
return;
}
int sz = str.length();
- StringBuffer unicode = new StringBuffer(4);
+ StrBuilder unicode = new StrBuilder(4);
boolean hadSlash = false;
boolean inUnicode = false;
for (int i = 0; i < sz; i++) {
@@ -330,7 +326,7 @@
unicode.append(ch);
if (unicode.length() == 4) {
// unicode now contains the four hex digits
- // which represents our unicode chacater
+ // which represents our unicode character
try {
int value = Integer.parseInt(unicode.toString(), 16);
out.write((char) value);
@@ -424,7 +420,7 @@
* @param out the Writer
used to output unescaped characters
* @param str the String
to unescape, may be null
* @throws IllegalArgumentException if the Writer is null
- * @throws IOException if error occurs on undelying Writer
+ * @throws IOException if error occurs on underlying Writer
*/
public static void unescapeJavaScript(Writer out, String str) throws IOException {
unescapeJava(out, str);
@@ -436,31 +432,83 @@
* Escapes the characters in a String
using HTML entities.
*
*
- * For example: "bread" & "butter" => "bread" & "butter".
+ * For example:
+ *
+ * "bread" & "butter"
+ * becomes:
+ *
+ * "bread" & "butter"
.
*
*
- * Supports all known HTML 4.0 entities, including funky accents.
- *
+ * Supports all known HTML 4.0 entities, including funky accents.
+ * Note that the commonly used apostrophe escape character (')
+ * is not a legal entity and so is not supported).
+ *
* @param str the String
to escape, may be null
* @return a new escaped String
, null
if null string input
*
* @see #unescapeHtml(String)
- * @see ISO Entities
- * @see HTML 3.2 Character Entities for ISO Latin-1
- * @see HTML 4.0 Character entity references
- * @see HTML 4.01 Character References
- * @see HTML 4.01 Code positions
- **/
+ * @see ISO Entities
+ * @see HTML 3.2 Character Entities for ISO Latin-1
+ * @see HTML 4.0 Character entity references
+ * @see HTML 4.01 Character References
+ * @see HTML 4.01 Code positions
+ */
public static String escapeHtml(String str) {
if (str == null) {
return null;
}
- //todo: add a version that takes a Writer
- //todo: rewrite underlying method to use a Writer instead of a StringBuffer
- return Entities.HTML40.escape(str);
+ try {
+ StringWriter writer = new StringWriter ((int)(str.length() * 1.5));
+ escapeHtml(writer, str);
+ return writer.toString();
+ } catch (IOException ioe) {
+ //should be impossible
+ throw new UnhandledException(ioe);
+ }
}
/**
+ * Escapes the characters in a String
using HTML entities and writes
+ * them to a Writer
.
+ *
+ *
+ * For example:
+ *
+ * "bread" & "butter"
+ * becomes:
+ * "bread" & "butter"
.
+ *
+ * Supports all known HTML 4.0 entities, including funky accents.
+ * Note that the commonly used apostrophe escape character (')
+ * is not a legal entity and so is not supported).
+ *
+ * @param writer the writer receiving the escaped string, not null
+ * @param string the String
to escape, may be null
+ * @throws IllegalArgumentException if the writer is null
+ * @throws IOException when Writer
passed throws the exception from
+ * calls to the {@link Writer#write(int)} methods.
+ *
+ * @see #escapeHtml(String)
+ * @see #unescapeHtml(String)
+ * @see ISO Entities
+ * @see HTML 3.2 Character Entities for ISO Latin-1
+ * @see HTML 4.0 Character entity references
+ * @see HTML 4.01 Character References
+ * @see HTML 4.01 Code positions
+ */
+ public static void escapeHtml(Writer writer, String string) throws IOException {
+ if (writer == null ) {
+ throw new IllegalArgumentException ("The Writer must not be null.");
+ }
+ if (string == null) {
+ return;
+ }
+ Entities.HTML40.escape(writer, string);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
* Unescapes a string containing entity escapes to a string
* containing the actual Unicode characters corresponding to the
* escapes. Supports HTML 4.0 entities.
@@ -474,55 +522,155 @@
*
* @param str the String
to unescape, may be null
* @return a new unescaped String
, null
if null string input
- * @see #escapeHtml(String)
- **/
+ * @see #escapeHtml(Writer, String)
+ */
public static String unescapeHtml(String str) {
if (str == null) {
return null;
}
- return Entities.HTML40.unescape(str);
+ try {
+ StringWriter writer = new StringWriter ((int)(str.length() * 1.5));
+ unescapeHtml(writer, str);
+ return writer.toString();
+ } catch (IOException ioe) {
+ //should be impossible
+ throw new UnhandledException(ioe);
+ }
}
/**
+ * Unescapes a string containing entity escapes to a string
+ * containing the actual Unicode characters corresponding to the
+ * escapes. Supports HTML 4.0 entities.
+ *
+ * For example, the string "<Français>"
+ * will become "<Français>"
+ *
+ * If an entity is unrecognized, it is left alone, and inserted
+ * verbatim into the result string. e.g. ">&zzzz;x" will
+ * become ">&zzzz;x".
+ *
+ * @param writer the writer receiving the unescaped string, not null
+ * @param string the String
to unescape, may be null
+ * @throws IllegalArgumentException if the writer is null
+ * @throws IOException if an IOException occurs
+ * @see #escapeHtml(String)
+ */
+ public static void unescapeHtml(Writer writer, String string) throws IOException {
+ if (writer == null ) {
+ throw new IllegalArgumentException ("The Writer must not be null.");
+ }
+ if (string == null) {
+ return;
+ }
+ Entities.HTML40.unescape(writer, string);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
* Escapes the characters in a String
using XML entities.
*
* For example: "bread" & "butter" =>
* "bread" & "butter".
*
*
- * Supports only the four basic XML entities (gt, lt, quot, amp).
+ *
Supports only the five basic XML entities (gt, lt, quot, amp, apos).
* Does not support DTDs or external entities.
*
+ * Note that unicode characters greater than 0x7f are currently escaped to
+ * their numerical \\u equivalent. This may change in future releases.
+ *
+ * @param writer the writer receiving the unescaped string, not null
* @param str the String
to escape, may be null
+ * @throws IllegalArgumentException if the writer is null
+ * @throws IOException if there is a problem writing
+ * @see #unescapeXml(java.lang.String)
+ */
+ public static void escapeXml(Writer writer, String str) throws IOException {
+ if (writer == null ) {
+ throw new IllegalArgumentException ("The Writer must not be null.");
+ }
+ if (str == null) {
+ return;
+ }
+ Entities.XML.escape(writer, str);
+ }
+
+ /**
+ * Escapes the characters in a String
using XML entities.
+ *
+ * For example: "bread" & "butter" =>
+ * "bread" & "butter".
+ *
+ *
+ * Supports only the five basic XML entities (gt, lt, quot, amp, apos).
+ * Does not support DTDs or external entities.
+ *
+ * Note that unicode characters greater than 0x7f are currently escaped to
+ * their numerical \\u equivalent. This may change in future releases.
+ *
+ * @param str the String
to escape, may be null
* @return a new escaped String
, null
if null string input
* @see #unescapeXml(java.lang.String)
- **/
+ */
public static String escapeXml(String str) {
if (str == null) {
return null;
}
return Entities.XML.escape(str);
}
+ //-----------------------------------------------------------------------
/**
* Unescapes a string containing XML entity escapes to a string
* containing the actual Unicode characters corresponding to the
* escapes.
*
- * Supports only the four basic XML entities (gt, lt, quot, amp).
+ *
Supports only the five basic XML entities (gt, lt, quot, amp, apos).
* Does not support DTDs or external entities.
*
+ * Note that numerical \\u unicode codes are unescaped to their respective
+ * unicode characters. This may change in future releases.
+ *
+ * @param writer the writer receiving the unescaped string, not null
* @param str the String
to unescape, may be null
+ * @throws IllegalArgumentException if the writer is null
+ * @throws IOException if there is a problem writing
+ * @see #escapeXml(String)
+ */
+ public static void unescapeXml(Writer writer, String str) throws IOException {
+ if (writer == null ) {
+ throw new IllegalArgumentException ("The Writer must not be null.");
+ }
+ if (str == null) {
+ return;
+ }
+ Entities.XML.unescape(writer, str);
+ }
+
+ /**
+ * Unescapes a string containing XML entity escapes to a string
+ * containing the actual Unicode characters corresponding to the
+ * escapes.
+ *
+ * Supports only the five basic XML entities (gt, lt, quot, amp, apos).
+ * Does not support DTDs or external entities.
+ *
+ * Note that numerical \\u unicode codes are unescaped to their respective
+ * unicode characters. This may change in future releases.
+ *
+ * @param str the String
to unescape, may be null
* @return a new unescaped String
, null
if null string input
* @see #escapeXml(String)
- **/
+ */
public static String unescapeXml(String str) {
if (str == null) {
return null;
}
return Entities.XML.unescape(str);
}
+ //-----------------------------------------------------------------------
/**
* Escapes the characters in a String
to be suitable to pass to
* an SQL query.
@@ -548,5 +696,166 @@
return StringUtils.replace(str, "'", "''");
}
-}
+ //-----------------------------------------------------------------------
+ /**
+ * Returns a String
value for a CSV column enclosed in double quotes,
+ * if required.
+ *
+ * If the value contains a comma, newline or double quote, then the
+ * String value is returned enclosed in double quotes.
+ *
+ *
+ * Any double quote characters in the value are escaped with another double quote.
+ *
+ * If the value does not contain a comma, newline or double quote, then the
+ * String value is returned unchanged.
+ *
+ *
+ * see Wikipedia and
+ * RFC 4180.
+ *
+ * @param str the input CSV column String, may be null
+ * @return the input String, enclosed in double quotes if the value contains a comma,
+ * newline or double quote, null
if null string input
+ * @since 2.4
+ */
+ public static String escapeCsv(String str) {
+ if (StringUtils.containsNone(str, CSV_SEARCH_CHARS)) {
+ return str;
+ }
+ try {
+ StringWriter writer = new StringWriter();
+ escapeCsv(writer, str);
+ return writer.toString();
+ } catch (IOException ioe) {
+ // this should never ever happen while writing to a StringWriter
+ throw new UnhandledException(ioe);
+ }
+ }
+
+ /**
+ * Writes a String
value for a CSV column enclosed in double quotes,
+ * if required.
+ *
+ * If the value contains a comma, newline or double quote, then the
+ * String value is written enclosed in double quotes.
+ *
+ *
+ * Any double quote characters in the value are escaped with another double quote.
+ *
+ * If the value does not contain a comma, newline or double quote, then the
+ * String value is written unchanged (null values are ignored).
+ *
+ *
+ * see Wikipedia and
+ * RFC 4180.
+ *
+ * @param str the input CSV column String, may be null
+ * @param out Writer to write input string to, enclosed in double quotes if it contains
+ * a comma, newline or double quote
+ * @throws IOException if error occurs on underlying Writer
+ * @since 2.4
+ */
+ public static void escapeCsv(Writer out, String str) throws IOException {
+ if (StringUtils.containsNone(str, CSV_SEARCH_CHARS)) {
+ if (str != null) {
+ out.write(str);
+ }
+ return;
+ }
+ out.write(CSV_QUOTE);
+ for (int i = 0; i < str.length(); i++) {
+ char c = str.charAt(i);
+ if (c == CSV_QUOTE) {
+ out.write(CSV_QUOTE); // escape double quote
+ }
+ out.write(c);
+ }
+ out.write(CSV_QUOTE);
+ }
+
+ /**
+ * Returns a String
value for an unescaped CSV column.
+ *
+ * If the value is enclosed in double quotes, and contains a comma, newline
+ * or double quote, then quotes are removed.
+ *
+ *
+ * Any double quote escaped characters (a pair of double quotes) are unescaped
+ * to just one double quote.
+ *
+ * If the value is not enclosed in double quotes, or is and does not contain a
+ * comma, newline or double quote, then the String value is returned unchanged.
+ *
+ *
+ * see Wikipedia and
+ * RFC 4180.
+ *
+ * @param str the input CSV column String, may be null
+ * @return the input String, with enclosing double quotes removed and embedded double
+ * quotes unescaped, null
if null string input
+ * @since 2.4
+ */
+ public static String unescapeCsv(String str) {
+ if (str == null) {
+ return null;
+ }
+ try {
+ StringWriter writer = new StringWriter();
+ unescapeCsv(writer, str);
+ return writer.toString();
+ } catch (IOException ioe) {
+ // this should never ever happen while writing to a StringWriter
+ throw new UnhandledException(ioe);
+ }
+ }
+
+ /**
+ * Returns a String
value for an unescaped CSV column.
+ *
+ * If the value is enclosed in double quotes, and contains a comma, newline
+ * or double quote, then quotes are removed.
+ *
+ *
+ * Any double quote escaped characters (a pair of double quotes) are unescaped
+ * to just one double quote.
+ *
+ * If the value is not enclosed in double quotes, or is and does not contain a
+ * comma, newline or double quote, then the String value is returned unchanged.
+ *
+ *
+ * see Wikipedia and
+ * RFC 4180.
+ *
+ * @param str the input CSV column String, may be null
+ * @param out Writer to write the input String to, with enclosing double quotes
+ * removed and embedded double quotes unescaped, null
if null string input
+ * @throws IOException if error occurs on underlying Writer
+ * @since 2.4
+ */
+ public static void unescapeCsv(Writer out, String str) throws IOException {
+ if (str == null) {
+ return;
+ }
+ if (str.length() < 2) {
+ out.write(str);
+ return;
+ }
+ if ( str.charAt(0) != CSV_QUOTE || str.charAt(str.length() - 1) != CSV_QUOTE ) {
+ out.write(str);
+ return;
+ }
+
+ // strip quotes
+ String quoteless = str.substring(1, str.length() - 1);
+
+ if ( StringUtils.containsAny(quoteless, CSV_SEARCH_CHARS) ) {
+ // deal with escaped quotes; ie) ""
+ str = StringUtils.replace(quoteless, CSV_QUOTE_STR + CSV_QUOTE_STR, CSV_QUOTE_STR);
+ }
+
+ out.write(str);
+ }
+
+}
Fisheye: Tag 6aa36ddefbf750d2b246992fee82df738a66eefa refers to a dead (removed) revision in file `3rdParty_sources/commons-lang/org/apache/commons/lang/StringPrintWriter.java'.
Fisheye: No comparison available. Pass `N' to diff?
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/StringUtils.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/StringUtils.java (.../StringUtils.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/StringUtils.java (.../StringUtils.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,86 +1,59 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
+import org.apache.commons.lang.text.StrBuilder;
+
/**
- * Operations on {@link java.lang.String} that are
+ *
Operations on {@link java.lang.String} that are
* null
safe.
- *
+ *
*
* - IsEmpty/IsBlank
* - checks if a String contains text
* - Trim/Strip
* - removes leading and trailing whitespace
* - Equals
* - compares two strings null-safe
+ * - startsWith
+ * - check if a String starts with a prefix null-safe
+ * - endsWith
+ * - check if a String ends with a suffix null-safe
* - IndexOf/LastIndexOf/Contains
* - null-safe index-of checks
*
- IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut
* - index-of any of a set of Strings
- * - ContainsOnly/ContainsNone
- * - does String contains only/none of these characters
+ * - ContainsOnly/ContainsNone/ContainsAny
+ * - does String contains only/none/any of these characters
* - Substring/Left/Right/Mid
* - null-safe substring extractions
* - SubstringBefore/SubstringAfter/SubstringBetween
* - substring extraction relative to other strings
* - Split/Join
* - splits a String into an array of substrings and vice versa
- * - Replace/Delete/Overlay
+ *
- Remove/Delete
+ * - removes part of a String
+ * - Replace/Overlay
* - Searches a String and replaces one String with another
* - Chomp/Chop
* - removes the last part of a String
@@ -89,8 +62,8 @@
* - UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize
* - changes the case of a String
* - CountMatches
- * - counts the number of occurrances of one String in another
- * - IsAlpha/IsNumeric/IsWhitespace
+ * - counts the number of occurrences of one String in another
+ * - IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable
* - checks the characters in a String
* - DefaultString
* - protects against a null input String
@@ -99,60 +72,65 @@
* - Abbreviate
* - abbreviates a string using ellipsis
* - Difference
- * - compares two Strings and reports on their differences
+ * - compares Strings and reports on their differences
* - LevensteinDistance
* - the number of changes needed to change one String into another
*
*
* The StringUtils
class defines certain words related to
* String handling.
- *
+ *
*
* - null -
null
* - empty - a zero-length string (
""
)
* - space - the space character (
' '
, char 32)
* - whitespace - the characters defined by {@link Character#isWhitespace(char)}
* - trim - the characters <= 32 as in {@link String#trim()}
*
- *
+ *
* StringUtils
handles null
input Strings quietly.
* That is to say that a null
input will return null
.
* Where a boolean
or int
is being returned
* details vary by method.
- *
- * A side effect of the null
handling is that a
+ *
+ *
A side effect of the null
handling is that a
* NullPointerException
should be considered a bug in
* StringUtils
(except for deprecated methods).
- *
+ *
* Methods in this class give sample code to explain their operation.
* The symbol *
is used to indicate any input including null
.
*
+ * #ThreadSafe#
* @see java.lang.String
+ * @author Apache Software Foundation
* @author Apache Jakarta Turbine
- * @author GenerationJavaCore
* @author Jon S. Stevens
- * @author Daniel Rall
+ * @author Daniel L. Rall
* @author Greg Coladonato
- * @author Henri Yandell
* @author Ed Korthof
* @author Rand McNeely
- * @author Stephen Colebourne
* @author Fredrik Westermarck
* @author Holger Krauth
* @author Alexander Day Chaffee
* @author Henning P. Schmiedehausen
* @author Arun Mammen Thomas
* @author Gary Gregory
* @author Phil Steitz
+ * @author Al Chou
+ * @author Michael Davey
+ * @author Reuben Sivan
+ * @author Chris Hyzer
+ * @author Scott Johnson
* @since 1.0
* @version $Id$
*/
+//@Immutable
public class StringUtils {
// Performance testing notes (JDK 1.4, Jul03, scolebourne)
// Whitespace:
// Character.isWhitespace() is faster than WHITESPACE.indexOf()
// where WHITESPACE is a string of all whitespace characters
- //
+ //
// Character access:
// String.charAt(n) versus toCharArray(), then array[n]
// String.charAt(n) is about 15% worse for a 10K string
@@ -163,29 +141,23 @@
// Append:
// String.concat about twice as fast as StringBuffer.append
// (not sure who tested this)
-
+
/**
* The empty String ""
.
* @since 2.0
*/
public static final String EMPTY = "";
-
+
/**
- * The maximum size to which the padding constant(s) can expand.
+ * Represents a failed index search.
+ * @since 2.1
*/
- private static final int PAD_LIMIT = 8192;
+ public static final int INDEX_NOT_FOUND = -1;
/**
- * An array of String
s used for padding.
- *
- * Used for efficient space padding. The length of each String expands as needed.
+ * The maximum size to which the padding constant(s) can expand.
*/
- private static final String[] PADDING = new String[Character.MAX_VALUE];
-
- static {
- // space padding is most common, start with 64 chars
- PADDING[32] = " ";
- }
+ private static final int PAD_LIMIT = 8192;
/**
* StringUtils
instances should NOT be constructed in
@@ -196,13 +168,14 @@
* instance to operate.
*/
public StringUtils() {
+ super();
}
// Empty checks
//-----------------------------------------------------------------------
/**
* Checks if a String is empty ("") or null.
- *
+ *
*
* StringUtils.isEmpty(null) = true
* StringUtils.isEmpty("") = true
@@ -214,17 +187,17 @@
* NOTE: This method changed in Lang version 2.0.
* It no longer trims the String.
* That functionality is available in isBlank().
- *
+ *
* @param str the String to check, may be null
* @return true
if the String is empty or null
*/
public static boolean isEmpty(String str) {
- return (str == null || str.length() == 0);
+ return str == null || str.length() == 0;
}
/**
* Checks if a String is not empty ("") and not null.
- *
+ *
*
* StringUtils.isNotEmpty(null) = false
* StringUtils.isNotEmpty("") = false
@@ -237,12 +210,12 @@
* @return true
if the String is not empty and not null
*/
public static boolean isNotEmpty(String str) {
- return (str != null && str.length() > 0);
+ return !StringUtils.isEmpty(str);
}
/**
* Checks if a String is whitespace, empty ("") or null.
- *
+ *
*
* StringUtils.isBlank(null) = true
* StringUtils.isBlank("") = true
@@ -261,7 +234,7 @@
return true;
}
for (int i = 0; i < strLen; i++) {
- if ((Character.isWhitespace(str.charAt(i)) == false) ) {
+ if ((Character.isWhitespace(str.charAt(i)) == false)) {
return false;
}
}
@@ -270,7 +243,7 @@
/**
* Checks if a String is not empty (""), not null and not whitespace only.
- *
+ *
*
* StringUtils.isNotBlank(null) = false
* StringUtils.isNotBlank("") = false
@@ -280,21 +253,12 @@
*
*
* @param str the String to check, may be null
- * @return true
if the String is
+ * @return true
if the String is
* not empty and not null and not whitespace
* @since 2.0
*/
public static boolean isNotBlank(String str) {
- int strLen;
- if (str == null || (strLen = str.length()) == 0) {
- return false;
- }
- for (int i = 0; i < strLen; i++) {
- if ((Character.isWhitespace(str.charAt(i)) == false) ) {
- return true;
- }
- }
- return false;
+ return !StringUtils.isBlank(str);
}
// Trim
@@ -303,7 +267,7 @@
* Removes control characters (char <= 32) from both
* ends of this String, handling null
by returning
* an empty String ("").
- *
+ *
*
* StringUtils.clean(null) = ""
* StringUtils.clean("") = ""
@@ -319,21 +283,21 @@
* Method will be removed in Commons Lang 3.0.
*/
public static String clean(String str) {
- return (str == null ? EMPTY : str.trim());
+ return str == null ? EMPTY : str.trim();
}
/**
* Removes control characters (char <= 32) from both
* ends of this String, handling null
by returning
* null
.
- *
+ *
* The String is trimmed using {@link String#trim()}.
* Trim removes start and end characters <= 32.
* To strip whitespace use {@link #strip(String)}.
- *
+ *
* To trim your choice of characters, use the
* {@link #strip(String, String)} methods.
- *
+ *
*
* StringUtils.trim(null) = null
* StringUtils.trim("") = ""
@@ -346,71 +310,71 @@
* @return the trimmed string, null
if null String input
*/
public static String trim(String str) {
- return (str == null ? null : str.trim());
+ return str == null ? null : str.trim();
}
- /**
- * Removes control characters (char <= 32) from both
- * ends of this String returning null
if the String is
+ /**
+ *
Removes control characters (char <= 32) from both
+ * ends of this String returning null
if the String is
* empty ("") after the trim or if it is null
.
- *
+ *
*
The String is trimmed using {@link String#trim()}.
* Trim removes start and end characters <= 32.
* To strip whitespace use {@link #stripToNull(String)}.
- *
+ *
*
* StringUtils.trimToNull(null) = null
* StringUtils.trimToNull("") = null
* StringUtils.trimToNull(" ") = null
* StringUtils.trimToNull("abc") = "abc"
* StringUtils.trimToNull(" abc ") = "abc"
*
- *
+ *
* @param str the String to be trimmed, may be null
- * @return the trimmed String,
+ * @return the trimmed String,
* null
if only chars <= 32, empty or null String input
* @since 2.0
*/
public static String trimToNull(String str) {
String ts = trim(str);
- return (ts == null || ts.length() == 0 ? null : ts);
+ return isEmpty(ts) ? null : ts;
}
- /**
- * Removes control characters (char <= 32) from both
+ /**
+ *
Removes control characters (char <= 32) from both
* ends of this String returning an empty String ("") if the String
* is empty ("") after the trim or if it is null
.
- *
+ *
*
The String is trimmed using {@link String#trim()}.
* Trim removes start and end characters <= 32.
* To strip whitespace use {@link #stripToEmpty(String)}.
- *
+ *
*
* StringUtils.trimToEmpty(null) = ""
* StringUtils.trimToEmpty("") = ""
* StringUtils.trimToEmpty(" ") = ""
* StringUtils.trimToEmpty("abc") = "abc"
* StringUtils.trimToEmpty(" abc ") = "abc"
*
- *
+ *
* @param str the String to be trimmed, may be null
* @return the trimmed String, or an empty String if null
input
* @since 2.0
*/
public static String trimToEmpty(String str) {
- return (str == null ? EMPTY : str.trim());
+ return str == null ? EMPTY : str.trim();
}
-
+
// Stripping
//-----------------------------------------------------------------------
/**
* Strips whitespace from the start and end of a String.
- *
+ *
* This is similar to {@link #trim(String)} but removes whitespace.
* Whitespace is defined by {@link Character#isWhitespace(char)}.
- *
+ *
* A null
input String returns null
.
- *
+ *
*
* StringUtils.strip(null) = null
* StringUtils.strip("") = ""
@@ -421,34 +385,34 @@
* StringUtils.strip(" abc ") = "abc"
* StringUtils.strip(" ab c ") = "ab c"
*
- *
+ *
* @param str the String to remove whitespace from, may be null
* @return the stripped String, null
if null String input
*/
public static String strip(String str) {
return strip(str, null);
}
-
- /**
+
+ /**
* Strips whitespace from the start and end of a String returning
* null
if the String is empty ("") after the strip.
- *
+ *
* This is similar to {@link #trimToNull(String)} but removes whitespace.
* Whitespace is defined by {@link Character#isWhitespace(char)}.
- *
+ *
*
- * StringUtils.strip(null) = null
- * StringUtils.strip("") = null
- * StringUtils.strip(" ") = null
- * StringUtils.strip("abc") = "abc"
- * StringUtils.strip(" abc") = "abc"
- * StringUtils.strip("abc ") = "abc"
- * StringUtils.strip(" abc ") = "abc"
- * StringUtils.strip(" ab c ") = "ab c"
+ * StringUtils.stripToNull(null) = null
+ * StringUtils.stripToNull("") = null
+ * StringUtils.stripToNull(" ") = null
+ * StringUtils.stripToNull("abc") = "abc"
+ * StringUtils.stripToNull(" abc") = "abc"
+ * StringUtils.stripToNull("abc ") = "abc"
+ * StringUtils.stripToNull(" abc ") = "abc"
+ * StringUtils.stripToNull(" ab c ") = "ab c"
*
- *
+ *
* @param str the String to be stripped, may be null
- * @return the stripped String,
+ * @return the stripped String,
* null
if whitespace, empty or null String input
* @since 2.0
*/
@@ -457,47 +421,47 @@
return null;
}
str = strip(str, null);
- return (str.length() == 0 ? null : str);
+ return str.length() == 0 ? null : str;
}
- /**
+ /**
* Strips whitespace from the start and end of a String returning
* an empty String if null
input.
- *
+ *
* This is similar to {@link #trimToEmpty(String)} but removes whitespace.
* Whitespace is defined by {@link Character#isWhitespace(char)}.
- *
+ *
*
- * StringUtils.strip(null) = ""
- * StringUtils.strip("") = ""
- * StringUtils.strip(" ") = ""
- * StringUtils.strip("abc") = "abc"
- * StringUtils.strip(" abc") = "abc"
- * StringUtils.strip("abc ") = "abc"
- * StringUtils.strip(" abc ") = "abc"
- * StringUtils.strip(" ab c ") = "ab c"
+ * StringUtils.stripToEmpty(null) = ""
+ * StringUtils.stripToEmpty("") = ""
+ * StringUtils.stripToEmpty(" ") = ""
+ * StringUtils.stripToEmpty("abc") = "abc"
+ * StringUtils.stripToEmpty(" abc") = "abc"
+ * StringUtils.stripToEmpty("abc ") = "abc"
+ * StringUtils.stripToEmpty(" abc ") = "abc"
+ * StringUtils.stripToEmpty(" ab c ") = "ab c"
*
- *
+ *
* @param str the String to be stripped, may be null
* @return the trimmed String, or an empty String if null
input
* @since 2.0
*/
public static String stripToEmpty(String str) {
- return (str == null ? EMPTY : strip(str, null));
+ return str == null ? EMPTY : strip(str, null);
}
-
+
/**
* Strips any of a set of characters from the start and end of a String.
* This is similar to {@link String#trim()} but allows the characters
* to be stripped to be controlled.
*
* A null
input String returns null
.
* An empty string ("") input returns the empty string.
- *
+ *
* If the stripChars String is null
, whitespace is
* stripped as defined by {@link Character#isWhitespace(char)}.
* Alternatively use {@link #strip(String)}.
- *
+ *
*
* StringUtils.strip(null, *) = null
* StringUtils.strip("", *) = ""
@@ -507,13 +471,13 @@
* StringUtils.strip(" abc ", null) = "abc"
* StringUtils.strip(" abcyx", "xyz") = " abc"
*
- *
+ *
* @param str the String to remove characters from, may be null
* @param stripChars the characters to remove, null treated as whitespace
* @return the stripped String, null
if null String input
*/
public static String strip(String str, String stripChars) {
- if (str == null || str.length() == 0) {
+ if (isEmpty(str)) {
return str;
}
str = stripStart(str, stripChars);
@@ -525,10 +489,10 @@
*
* A null
input String returns null
.
* An empty string ("") input returns the empty string.
- *
+ *
* If the stripChars String is null
, whitespace is
* stripped as defined by {@link Character#isWhitespace(char)}.
- *
+ *
*
* StringUtils.stripStart(null, *) = null
* StringUtils.stripStart("", *) = ""
@@ -539,7 +503,7 @@
* StringUtils.stripStart(" abc ", null) = "abc "
* StringUtils.stripStart("yxabc ", "xyz") = "abc "
*
- *
+ *
* @param str the String to remove characters from, may be null
* @param stripChars the characters to remove, null treated as whitespace
* @return the stripped String, null
if null String input
@@ -557,7 +521,7 @@
} else if (stripChars.length() == 0) {
return str;
} else {
- while ((start != strLen) && (stripChars.indexOf(str.charAt(start)) != -1)) {
+ while ((start != strLen) && (stripChars.indexOf(str.charAt(start)) != INDEX_NOT_FOUND)) {
start++;
}
}
@@ -569,10 +533,10 @@
*
* A null
input String returns null
.
* An empty string ("") input returns the empty string.
- *
+ *
* If the stripChars String is null
, whitespace is
* stripped as defined by {@link Character#isWhitespace(char)}.
- *
+ *
*
* StringUtils.stripEnd(null, *) = null
* StringUtils.stripEnd("", *) = ""
@@ -582,26 +546,27 @@
* StringUtils.stripEnd("abc ", null) = "abc"
* StringUtils.stripEnd(" abc ", null) = " abc"
* StringUtils.stripEnd(" abcyx", "xyz") = " abc"
+ * StringUtils.stripEnd("120.00", ".0") = "12"
*
- *
+ *
* @param str the String to remove characters from, may be null
- * @param stripChars the characters to remove, null treated as whitespace
+ * @param stripChars the set of characters to remove, null treated as whitespace
* @return the stripped String, null
if null String input
*/
public static String stripEnd(String str, String stripChars) {
int end;
if (str == null || (end = str.length()) == 0) {
return str;
}
-
+
if (stripChars == null) {
while ((end != 0) && Character.isWhitespace(str.charAt(end - 1))) {
end--;
}
} else if (stripChars.length() == 0) {
return str;
} else {
- while ((end != 0) && (stripChars.indexOf(str.charAt(end - 1)) != -1)) {
+ while ((end != 0) && (stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND)) {
end--;
}
}
@@ -618,21 +583,21 @@
* A null
array will return null
.
* An empty array will return itself.
* A null
array entry will be ignored.
- *
+ *
*
* StringUtils.stripAll(null) = null
* StringUtils.stripAll([]) = []
* StringUtils.stripAll(["abc", " abc"]) = ["abc", "abc"]
* StringUtils.stripAll(["abc ", null]) = ["abc", null]
*
- *
+ *
* @param strs the array to remove whitespace from, may be null
* @return the stripped Strings, null
if null array input
*/
public static String[] stripAll(String[] strs) {
return stripAll(strs, null);
}
-
+
/**
* Strips any of a set of characters from the start and end of every
* String in an array.
@@ -644,7 +609,7 @@
* A null
array entry will be ignored.
* A null
stripChars will strip whitespace as defined by
* {@link Character#isWhitespace(char)}.
- *
+ *
*
* StringUtils.stripAll(null, *) = null
* StringUtils.stripAll([], *) = []
@@ -653,7 +618,7 @@
* StringUtils.stripAll(["abc ", null], "yz") = ["abc ", null]
* StringUtils.stripAll(["yabcz", null], "yz") = ["abc", null]
*
- *
+ *
* @param strs the array to remove characters from, may be null
* @param stripChars the characters to remove, null treated as whitespace
* @return the stripped Strings, null
if null array input
@@ -668,7 +633,7 @@
newArr[i] = strip(strs[i], stripChars);
}
return newArr;
- }
+ }
// Equals
//-----------------------------------------------------------------------
@@ -685,15 +650,15 @@
* StringUtils.equals("abc", "abc") = true
* StringUtils.equals("abc", "ABC") = false
*
- *
+ *
* @see java.lang.String#equals(Object)
* @param str1 the first String, may be null
* @param str2 the second String, may be null
* @return true
if the Strings are equal, case sensitive, or
* both null
*/
public static boolean equals(String str1, String str2) {
- return (str1 == null ? str2 == null : str1.equals(str2));
+ return str1 == null ? str2 == null : str1.equals(str2);
}
/**
@@ -710,15 +675,15 @@
* StringUtils.equalsIgnoreCase("abc", "abc") = true
* StringUtils.equalsIgnoreCase("abc", "ABC") = true
*
- *
+ *
* @see java.lang.String#equalsIgnoreCase(String)
* @param str1 the first String, may be null
* @param str2 the second String, may be null
* @return true
if the Strings are equal, case insensitive, or
* both null
*/
public static boolean equalsIgnoreCase(String str1, String str2) {
- return (str1 == null ? str2 == null : str1.equalsIgnoreCase(str2));
+ return str1 == null ? str2 == null : str1.equalsIgnoreCase(str2);
}
// IndexOf
@@ -727,37 +692,37 @@
* Finds the first index within a String, handling null
.
* This method uses {@link String#indexOf(int)}.
*
- * A null
or empty ("") String will return -1
.
- *
+ * A null
or empty ("") String will return INDEX_NOT_FOUND (-1)
.
+ *
*
* StringUtils.indexOf(null, *) = -1
* StringUtils.indexOf("", *) = -1
* StringUtils.indexOf("aabaabaa", 'a') = 0
* StringUtils.indexOf("aabaabaa", 'b') = 2
*
- *
+ *
* @param str the String to check, may be null
* @param searchChar the character to find
- * @return the first index of the search character,
+ * @return the first index of the search character,
* -1 if no match or null
string input
* @since 2.0
*/
public static int indexOf(String str, char searchChar) {
- if (str == null || str.length() == 0) {
- return -1;
+ if (isEmpty(str)) {
+ return INDEX_NOT_FOUND;
}
return str.indexOf(searchChar);
}
-
+
/**
* Finds the first index within a String from a start position,
* handling null
.
* This method uses {@link String#indexOf(int, int)}.
*
- * A null
or empty ("") String will return -1
.
+ *
A null
or empty ("") String will return (INDEX_NOT_FOUND) -1
.
* A negative start position is treated as zero.
* A start position greater than the string length returns -1
.
- *
+ *
*
* StringUtils.indexOf(null, *, *) = -1
* StringUtils.indexOf("", *, *) = -1
@@ -766,37 +731,38 @@
* StringUtils.indexOf("aabaabaa", 'b', 9) = -1
* StringUtils.indexOf("aabaabaa", 'b', -1) = 2
*
- *
+ *
* @param str the String to check, may be null
* @param searchChar the character to find
* @param startPos the start position, negative treated as zero
- * @return the first index of the search character,
+ * @return the first index of the search character,
* -1 if no match or null
string input
* @since 2.0
*/
public static int indexOf(String str, char searchChar, int startPos) {
- if (str == null || str.length() == 0) {
- return -1;
+ if (isEmpty(str)) {
+ return INDEX_NOT_FOUND;
}
return str.indexOf(searchChar, startPos);
}
-
+
/**
* Finds the first index within a String, handling null
.
* This method uses {@link String#indexOf(String)}.
*
* A null
String will return -1
.
- *
+ *
*
* StringUtils.indexOf(null, *) = -1
* StringUtils.indexOf(*, null) = -1
* StringUtils.indexOf("", "") = 0
+ * StringUtils.indexOf("", *) = -1 (except when * = "")
* StringUtils.indexOf("aabaabaa", "a") = 0
* StringUtils.indexOf("aabaabaa", "b") = 2
* StringUtils.indexOf("aabaabaa", "ab") = 1
* StringUtils.indexOf("aabaabaa", "") = 0
*
- *
+ *
* @param str the String to check, may be null
* @param searchStr the String to find, may be null
* @return the first index of the search String,
@@ -805,12 +771,86 @@
*/
public static int indexOf(String str, String searchStr) {
if (str == null || searchStr == null) {
- return -1;
+ return INDEX_NOT_FOUND;
}
return str.indexOf(searchStr);
}
-
+
/**
+ * Finds the n-th index within a String, handling null
.
+ * This method uses {@link String#indexOf(String)}.
+ *
+ * A null
String will return -1
.
+ *
+ *
+ * StringUtils.ordinalIndexOf(null, *, *) = -1
+ * StringUtils.ordinalIndexOf(*, null, *) = -1
+ * StringUtils.ordinalIndexOf("", "", *) = 0
+ * StringUtils.ordinalIndexOf("aabaabaa", "a", 1) = 0
+ * StringUtils.ordinalIndexOf("aabaabaa", "a", 2) = 1
+ * StringUtils.ordinalIndexOf("aabaabaa", "b", 1) = 2
+ * StringUtils.ordinalIndexOf("aabaabaa", "b", 2) = 5
+ * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1
+ * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4
+ * StringUtils.ordinalIndexOf("aabaabaa", "", 1) = 0
+ * StringUtils.ordinalIndexOf("aabaabaa", "", 2) = 0
+ *
+ *
+ * Note that 'head(String str, int n)' may be implemented as:
+ *
+ *
+ * str.substring(0, lastOrdinalIndexOf(str, "\n", n))
+ *
+ *
+ * @param str the String to check, may be null
+ * @param searchStr the String to find, may be null
+ * @param ordinal the n-th searchStr
to find
+ * @return the n-th index of the search String,
+ * -1
(INDEX_NOT_FOUND
) if no match or null
string input
+ * @since 2.1
+ */
+ public static int ordinalIndexOf(String str, String searchStr, int ordinal) {
+ return ordinalIndexOf(str, searchStr, ordinal, false);
+ }
+
+ /**
+ * Finds the n-th index within a String, handling null
.
+ * This method uses {@link String#indexOf(String)}.
+ *
+ * A null
String will return -1
.
+ *
+ * @param str the String to check, may be null
+ * @param searchStr the String to find, may be null
+ * @param ordinal the n-th searchStr
to find
+ * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf()
+ * @return the n-th index of the search String,
+ * -1
(INDEX_NOT_FOUND
) if no match or null
string input
+ */
+ // Shared code between ordinalIndexOf(String,String,int) and lastOrdinalIndexOf(String,String,int)
+ private static int ordinalIndexOf(String str, String searchStr, int ordinal, boolean lastIndex) {
+ if (str == null || searchStr == null || ordinal <= 0) {
+ return INDEX_NOT_FOUND;
+ }
+ if (searchStr.length() == 0) {
+ return lastIndex ? str.length() : 0;
+ }
+ int found = 0;
+ int index = lastIndex ? str.length() : INDEX_NOT_FOUND;
+ do {
+ if(lastIndex) {
+ index = str.lastIndexOf(searchStr, index - 1);
+ } else {
+ index = str.indexOf(searchStr, index + 1);
+ }
+ if (index < 0) {
+ return index;
+ }
+ found++;
+ } while (found < ordinal);
+ return index;
+ }
+
+ /**
* Finds the first index within a String, handling null
.
* This method uses {@link String#indexOf(String, int)}.
*
@@ -819,11 +859,12 @@
* An empty ("") search String always matches.
* A start position greater than the string length only matches
* an empty search String.
- *
+ *
*
* StringUtils.indexOf(null, *, *) = -1
* StringUtils.indexOf(*, null, *) = -1
* StringUtils.indexOf("", "", 0) = 0
+ * StringUtils.indexOf("", *, 0) = -1 (except when * = "")
* StringUtils.indexOf("aabaabaa", "a", 0) = 0
* StringUtils.indexOf("aabaabaa", "b", 0) = 2
* StringUtils.indexOf("aabaabaa", "ab", 0) = 1
@@ -833,7 +874,7 @@
* StringUtils.indexOf("aabaabaa", "", 2) = 2
* StringUtils.indexOf("abc", "", 9) = 3
*
- *
+ *
* @param str the String to check, may be null
* @param searchStr the String to find, may be null
* @param startPos the start position, negative treated as zero
@@ -843,43 +884,124 @@
*/
public static int indexOf(String str, String searchStr, int startPos) {
if (str == null || searchStr == null) {
- return -1;
+ return INDEX_NOT_FOUND;
}
// JDK1.2/JDK1.3 have a bug, when startPos > str.length for "", hence
if (searchStr.length() == 0 && startPos >= str.length()) {
return str.length();
}
return str.indexOf(searchStr, startPos);
}
-
+
+ /**
+ * Case in-sensitive find of the first index within a String.
+ *
+ * A null
String will return -1
.
+ * A negative start position is treated as zero.
+ * An empty ("") search String always matches.
+ * A start position greater than the string length only matches
+ * an empty search String.
+ *
+ *
+ * StringUtils.indexOfIgnoreCase(null, *) = -1
+ * StringUtils.indexOfIgnoreCase(*, null) = -1
+ * StringUtils.indexOfIgnoreCase("", "") = 0
+ * StringUtils.indexOfIgnoreCase("aabaabaa", "a") = 0
+ * StringUtils.indexOfIgnoreCase("aabaabaa", "b") = 2
+ * StringUtils.indexOfIgnoreCase("aabaabaa", "ab") = 1
+ *
+ *
+ * @param str the String to check, may be null
+ * @param searchStr the String to find, may be null
+ * @return the first index of the search String,
+ * -1 if no match or null
string input
+ * @since 2.5
+ */
+ public static int indexOfIgnoreCase(String str, String searchStr) {
+ return indexOfIgnoreCase(str, searchStr, 0);
+ }
+
+ /**
+ * Case in-sensitive find of the first index within a String
+ * from the specified position.
+ *
+ * A null
String will return -1
.
+ * A negative start position is treated as zero.
+ * An empty ("") search String always matches.
+ * A start position greater than the string length only matches
+ * an empty search String.
+ *
+ *
+ * StringUtils.indexOfIgnoreCase(null, *, *) = -1
+ * StringUtils.indexOfIgnoreCase(*, null, *) = -1
+ * StringUtils.indexOfIgnoreCase("", "", 0) = 0
+ * StringUtils.indexOfIgnoreCase("aabaabaa", "A", 0) = 0
+ * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 0) = 2
+ * StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1
+ * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 3) = 5
+ * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 9) = -1
+ * StringUtils.indexOfIgnoreCase("aabaabaa", "B", -1) = 2
+ * StringUtils.indexOfIgnoreCase("aabaabaa", "", 2) = 2
+ * StringUtils.indexOfIgnoreCase("abc", "", 9) = 3
+ *
+ *
+ * @param str the String to check, may be null
+ * @param searchStr the String to find, may be null
+ * @param startPos the start position, negative treated as zero
+ * @return the first index of the search String,
+ * -1 if no match or null
string input
+ * @since 2.5
+ */
+ public static int indexOfIgnoreCase(String str, String searchStr, int startPos) {
+ if (str == null || searchStr == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startPos < 0) {
+ startPos = 0;
+ }
+ int endLimit = (str.length() - searchStr.length()) + 1;
+ if (startPos > endLimit) {
+ return INDEX_NOT_FOUND;
+ }
+ if (searchStr.length() == 0) {
+ return startPos;
+ }
+ for (int i = startPos; i < endLimit; i++) {
+ if (str.regionMatches(true, i, searchStr, 0, searchStr.length())) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
// LastIndexOf
//-----------------------------------------------------------------------
/**
* Finds the last index within a String, handling null
.
* This method uses {@link String#lastIndexOf(int)}.
*
* A null
or empty ("") String will return -1
.
- *
+ *
*
* StringUtils.lastIndexOf(null, *) = -1
* StringUtils.lastIndexOf("", *) = -1
* StringUtils.lastIndexOf("aabaabaa", 'a') = 7
* StringUtils.lastIndexOf("aabaabaa", 'b') = 5
*
- *
+ *
* @param str the String to check, may be null
* @param searchChar the character to find
- * @return the last index of the search character,
+ * @return the last index of the search character,
* -1 if no match or null
string input
* @since 2.0
*/
public static int lastIndexOf(String str, char searchChar) {
- if (str == null || str.length() == 0) {
- return -1;
+ if (isEmpty(str)) {
+ return INDEX_NOT_FOUND;
}
return str.lastIndexOf(searchChar);
}
-
+
/**
* Finds the last index within a String from a start position,
* handling null
.
@@ -888,7 +1010,7 @@
*
A null
or empty ("") String will return -1
.
* A negative start position returns -1
.
* A start position greater than the string length searches the whole string.
- *
+ *
*
* StringUtils.lastIndexOf(null, *, *) = -1
* StringUtils.lastIndexOf("", *, *) = -1
@@ -899,37 +1021,37 @@
* StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1
* StringUtils.lastIndexOf("aabaabaa", 'a', 0) = 0
*
- *
+ *
* @param str the String to check, may be null
* @param searchChar the character to find
* @param startPos the start position
- * @return the last index of the search character,
+ * @return the last index of the search character,
* -1 if no match or null
string input
* @since 2.0
*/
public static int lastIndexOf(String str, char searchChar, int startPos) {
- if (str == null || str.length() == 0) {
- return -1;
+ if (isEmpty(str)) {
+ return INDEX_NOT_FOUND;
}
return str.lastIndexOf(searchChar, startPos);
}
-
+
/**
* Finds the last index within a String, handling null
.
* This method uses {@link String#lastIndexOf(String)}.
*
* A null
String will return -1
.
- *
+ *
*
* StringUtils.lastIndexOf(null, *) = -1
* StringUtils.lastIndexOf(*, null) = -1
* StringUtils.lastIndexOf("", "") = 0
- * StringUtils.lastIndexOf("aabaabaa", "a") = 0
- * StringUtils.lastIndexOf("aabaabaa", "b") = 2
- * StringUtils.lastIndexOf("aabaabaa", "ab") = 1
+ * StringUtils.lastIndexOf("aabaabaa", "a") = 7
+ * StringUtils.lastIndexOf("aabaabaa", "b") = 5
+ * StringUtils.lastIndexOf("aabaabaa", "ab") = 4
* StringUtils.lastIndexOf("aabaabaa", "") = 8
*
- *
+ *
* @param str the String to check, may be null
* @param searchStr the String to find, may be null
* @return the last index of the search String,
@@ -938,20 +1060,57 @@
*/
public static int lastIndexOf(String str, String searchStr) {
if (str == null || searchStr == null) {
- return -1;
+ return INDEX_NOT_FOUND;
}
return str.lastIndexOf(searchStr);
}
-
+
/**
+ * Finds the n-th last index within a String, handling null
.
+ * This method uses {@link String#lastIndexOf(String)}.
+ *
+ * A null
String will return -1
.
+ *
+ *
+ * StringUtils.lastOrdinalIndexOf(null, *, *) = -1
+ * StringUtils.lastOrdinalIndexOf(*, null, *) = -1
+ * StringUtils.lastOrdinalIndexOf("", "", *) = 0
+ * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 1) = 7
+ * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 2) = 6
+ * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 1) = 5
+ * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 2) = 2
+ * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 1) = 4
+ * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 2) = 1
+ * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 1) = 8
+ * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 2) = 8
+ *
+ *
+ * Note that 'tail(String str, int n)' may be implemented as:
+ *
+ *
+ * str.substring(lastOrdinalIndexOf(str, "\n", n) + 1)
+ *
+ *
+ * @param str the String to check, may be null
+ * @param searchStr the String to find, may be null
+ * @param ordinal the n-th last searchStr
to find
+ * @return the n-th last index of the search String,
+ * -1
(INDEX_NOT_FOUND
) if no match or null
string input
+ * @since 2.5
+ */
+ public static int lastOrdinalIndexOf(String str, String searchStr, int ordinal) {
+ return ordinalIndexOf(str, searchStr, ordinal, true);
+ }
+
+ /**
* Finds the first index within a String, handling null
.
* This method uses {@link String#lastIndexOf(String, int)}.
*
* A null
String will return -1
.
* A negative start position returns -1
.
* An empty ("") search String always matches unless the start position is negative.
* A start position greater than the string length searches the whole string.
- *
+ *
*
* StringUtils.lastIndexOf(null, *, *) = -1
* StringUtils.lastIndexOf(*, null, *) = -1
@@ -963,7 +1122,7 @@
* StringUtils.lastIndexOf("aabaabaa", "a", 0) = 0
* StringUtils.lastIndexOf("aabaabaa", "b", 0) = -1
*
- *
+ *
* @param str the String to check, may be null
* @param searchStr the String to find, may be null
* @param startPos the start position, negative treated as zero
@@ -973,45 +1132,124 @@
*/
public static int lastIndexOf(String str, String searchStr, int startPos) {
if (str == null || searchStr == null) {
- return -1;
+ return INDEX_NOT_FOUND;
}
return str.lastIndexOf(searchStr, startPos);
}
-
+
+ /**
+ * Case in-sensitive find of the last index within a String.
+ *
+ * A null
String will return -1
.
+ * A negative start position returns -1
.
+ * An empty ("") search String always matches unless the start position is negative.
+ * A start position greater than the string length searches the whole string.
+ *
+ *
+ * StringUtils.lastIndexOfIgnoreCase(null, *) = -1
+ * StringUtils.lastIndexOfIgnoreCase(*, null) = -1
+ * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A") = 7
+ * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B") = 5
+ * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB") = 4
+ *
+ *
+ * @param str the String to check, may be null
+ * @param searchStr the String to find, may be null
+ * @return the first index of the search String,
+ * -1 if no match or null
string input
+ * @since 2.5
+ */
+ public static int lastIndexOfIgnoreCase(String str, String searchStr) {
+ if (str == null || searchStr == null) {
+ return INDEX_NOT_FOUND;
+ }
+ return lastIndexOfIgnoreCase(str, searchStr, str.length());
+ }
+
+ /**
+ * Case in-sensitive find of the last index within a String
+ * from the specified position.
+ *
+ * A null
String will return -1
.
+ * A negative start position returns -1
.
+ * An empty ("") search String always matches unless the start position is negative.
+ * A start position greater than the string length searches the whole string.
+ *
+ *
+ * StringUtils.lastIndexOfIgnoreCase(null, *, *) = -1
+ * StringUtils.lastIndexOfIgnoreCase(*, null, *) = -1
+ * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 8) = 7
+ * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 8) = 5
+ * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB", 8) = 4
+ * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 9) = 5
+ * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", -1) = -1
+ * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 0) = 0
+ * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 0) = -1
+ *
+ *
+ * @param str the String to check, may be null
+ * @param searchStr the String to find, may be null
+ * @param startPos the start position
+ * @return the first index of the search String,
+ * -1 if no match or null
string input
+ * @since 2.5
+ */
+ public static int lastIndexOfIgnoreCase(String str, String searchStr, int startPos) {
+ if (str == null || searchStr == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startPos > (str.length() - searchStr.length())) {
+ startPos = str.length() - searchStr.length();
+ }
+ if (startPos < 0) {
+ return INDEX_NOT_FOUND;
+ }
+ if (searchStr.length() == 0) {
+ return startPos;
+ }
+
+ for (int i = startPos; i >= 0; i--) {
+ if (str.regionMatches(true, i, searchStr, 0, searchStr.length())) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
// Contains
//-----------------------------------------------------------------------
/**
* Checks if String contains a search character, handling null
.
* This method uses {@link String#indexOf(int)}.
*
* A null
or empty ("") String will return false
.
- *
+ *
*
* StringUtils.contains(null, *) = false
* StringUtils.contains("", *) = false
* StringUtils.contains("abc", 'a') = true
* StringUtils.contains("abc", 'z') = false
*
- *
+ *
* @param str the String to check, may be null
* @param searchChar the character to find
- * @return true if the String contains the search character,
+ * @return true if the String contains the search character,
* false if not or null
string input
* @since 2.0
*/
public static boolean contains(String str, char searchChar) {
- if (str == null || str.length() == 0) {
+ if (isEmpty(str)) {
return false;
}
- return (str.indexOf(searchChar) >= 0);
+ return str.indexOf(searchChar) >= 0;
}
-
+
/**
- * Find the first index within a String, handling null
.
- * This method uses {@link String#indexOf(int)}.
+ * Checks if String contains a search String, handling null
.
+ * This method uses {@link String#indexOf(String)}.
*
* A null
String will return false
.
- *
+ *
*
* StringUtils.contains(null, *) = false
* StringUtils.contains(*, null) = false
@@ -1020,20 +1258,57 @@
* StringUtils.contains("abc", "a") = true
* StringUtils.contains("abc", "z") = false
*
- *
+ *
* @param str the String to check, may be null
* @param searchStr the String to find, may be null
- * @return true if the String contains the search character,
+ * @return true if the String contains the search String,
* false if not or null
string input
* @since 2.0
*/
public static boolean contains(String str, String searchStr) {
if (str == null || searchStr == null) {
return false;
}
- return (str.indexOf(searchStr) >= 0);
+ return str.indexOf(searchStr) >= 0;
}
-
+
+ /**
+ * Checks if String contains a search String irrespective of case,
+ * handling null
. Case-insensitivity is defined as by
+ * {@link String#equalsIgnoreCase(String)}.
+ *
+ *
A null
String will return false
.
+ *
+ *
+ * StringUtils.contains(null, *) = false
+ * StringUtils.contains(*, null) = false
+ * StringUtils.contains("", "") = true
+ * StringUtils.contains("abc", "") = true
+ * StringUtils.contains("abc", "a") = true
+ * StringUtils.contains("abc", "z") = false
+ * StringUtils.contains("abc", "A") = true
+ * StringUtils.contains("abc", "Z") = false
+ *
+ *
+ * @param str the String to check, may be null
+ * @param searchStr the String to find, may be null
+ * @return true if the String contains the search String irrespective of
+ * case or false if not or null
string input
+ */
+ public static boolean containsIgnoreCase(String str, String searchStr) {
+ if (str == null || searchStr == null) {
+ return false;
+ }
+ int len = searchStr.length();
+ int max = str.length() - len;
+ for (int i = 0; i <= max; i++) {
+ if (str.regionMatches(true, i, searchStr, 0, len)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
// IndexOfAny chars
//-----------------------------------------------------------------------
/**
@@ -1042,7 +1317,7 @@
*
* A null
String will return -1
.
* A null
or zero length search array will return -1
.
- *
+ *
*
* StringUtils.indexOfAny(null, *) = -1
* StringUtils.indexOfAny("", *) = -1
@@ -1052,34 +1327,45 @@
* StringUtils.indexOfAny("zzabyycdxx",['b','y']) = 3
* StringUtils.indexOfAny("aba", ['z']) = -1
*
- *
+ *
* @param str the String to check, may be null
* @param searchChars the chars to search for, may be null
* @return the index of any of the chars, -1 if no match or null input
* @since 2.0
*/
- public static int indexOfAny(String str, char[] searchChars) {
- if (str == null || str.length() == 0 || searchChars == null || searchChars.length == 0) {
- return -1;
- }
- for (int i = 0; i < str.length(); i ++) {
- char ch = str.charAt(i);
- for (int j = 0; j < searchChars.length; j++) {
- if (searchChars[j] == ch) {
- return i;
- }
- }
- }
- return -1;
- }
+ public static int indexOfAny(String str, char[] searchChars) {
+ if (isEmpty(str) || ArrayUtils.isEmpty(searchChars)) {
+ return INDEX_NOT_FOUND;
+ }
+ int csLen = str.length();
+ int csLast = csLen - 1;
+ int searchLen = searchChars.length;
+ int searchLast = searchLen - 1;
+ for (int i = 0; i < csLen; i++) {
+ char ch = str.charAt(i);
+ for (int j = 0; j < searchLen; j++) {
+ if (searchChars[j] == ch) {
+ if (i < csLast && j < searchLast && CharUtils.isHighSurrogate(ch)) {
+ // ch is a supplementary character
+ if (searchChars[j + 1] == str.charAt(i + 1)) {
+ return i;
+ }
+ } else {
+ return i;
+ }
+ }
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
/**
* Search a String to find the first index of any
* character in the given set of characters.
*
* A null
String will return -1
.
* A null
search string will return -1
.
- *
+ *
*
* StringUtils.indexOfAny(null, *) = -1
* StringUtils.indexOfAny("", *) = -1
@@ -1089,19 +1375,108 @@
* StringUtils.indexOfAny("zzabyycdxx", "by") = 3
* StringUtils.indexOfAny("aba","z") = -1
*
- *
+ *
* @param str the String to check, may be null
* @param searchChars the chars to search for, may be null
* @return the index of any of the chars, -1 if no match or null input
* @since 2.0
*/
public static int indexOfAny(String str, String searchChars) {
- if (str == null || str.length() == 0 || searchChars == null || searchChars.length() == 0) {
- return -1;
+ if (isEmpty(str) || isEmpty(searchChars)) {
+ return INDEX_NOT_FOUND;
}
return indexOfAny(str, searchChars.toCharArray());
}
+ // ContainsAny
+ //-----------------------------------------------------------------------
+ /**
+ * Checks if the String contains any character in the given
+ * set of characters.
+ *
+ * A null
String will return false
.
+ * A null
or zero length search array will return false
.
+ *
+ *
+ * StringUtils.containsAny(null, *) = false
+ * StringUtils.containsAny("", *) = false
+ * StringUtils.containsAny(*, null) = false
+ * StringUtils.containsAny(*, []) = false
+ * StringUtils.containsAny("zzabyycdxx",['z','a']) = true
+ * StringUtils.containsAny("zzabyycdxx",['b','y']) = true
+ * StringUtils.containsAny("aba", ['z']) = false
+ *
+ *
+ * @param str the String to check, may be null
+ * @param searchChars the chars to search for, may be null
+ * @return the true
if any of the chars are found,
+ * false
if no match or null input
+ * @since 2.4
+ */
+ public static boolean containsAny(String str, char[] searchChars) {
+ if (isEmpty(str) || ArrayUtils.isEmpty(searchChars)) {
+ return false;
+ }
+ int csLength = str.length();
+ int searchLength = searchChars.length;
+ int csLast = csLength - 1;
+ int searchLast = searchLength - 1;
+ for (int i = 0; i < csLength; i++) {
+ char ch = str.charAt(i);
+ for (int j = 0; j < searchLength; j++) {
+ if (searchChars[j] == ch) {
+ if (CharUtils.isHighSurrogate(ch)) {
+ if (j == searchLast) {
+ // missing low surrogate, fine, like String.indexOf(String)
+ return true;
+ }
+ if (i < csLast && searchChars[j + 1] == str.charAt(i + 1)) {
+ return true;
+ }
+ } else {
+ // ch is in the Basic Multilingual Plane
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ *
+ * Checks if the String contains any character in the given set of characters.
+ *
+ *
+ *
+ * A null
String will return false
. A null
search string will return
+ * false
.
+ *
+ *
+ *
+ * StringUtils.containsAny(null, *) = false
+ * StringUtils.containsAny("", *) = false
+ * StringUtils.containsAny(*, null) = false
+ * StringUtils.containsAny(*, "") = false
+ * StringUtils.containsAny("zzabyycdxx", "za") = true
+ * StringUtils.containsAny("zzabyycdxx", "by") = true
+ * StringUtils.containsAny("aba","z") = false
+ *
+ *
+ * @param str
+ * the String to check, may be null
+ * @param searchChars
+ * the chars to search for, may be null
+ * @return the true
if any of the chars are found, false
if no match or null input
+ * @since 2.4
+ */
+ public static boolean containsAny(String str, String searchChars) {
+ if (searchChars == null) {
+ return false;
+ }
+ return containsAny(str, searchChars.toCharArray());
+ }
+
// IndexOfAnyBut chars
//-----------------------------------------------------------------------
/**
@@ -1110,70 +1485,91 @@
*
* A null
String will return -1
.
* A null
or zero length search array will return -1
.
- *
+ *
*
- * StringUtils.indexOfAnyBut(null, *) = -1
- * StringUtils.indexOfAnyBut("", *) = -1
- * StringUtils.indexOfAnyBut(*, null) = -1
- * StringUtils.indexOfAnyBut(*, []) = -1
- * StringUtils.indexOfAnyBut("zzabyycdxx",'za') = 3
- * StringUtils.indexOfAnyBut("zzabyycdxx", '') = 0
- * StringUtils.indexOfAnyBut("aba", 'ab') = -1
+ * StringUtils.indexOfAnyBut(null, *) = -1
+ * StringUtils.indexOfAnyBut("", *) = -1
+ * StringUtils.indexOfAnyBut(*, null) = -1
+ * StringUtils.indexOfAnyBut(*, []) = -1
+ * StringUtils.indexOfAnyBut("zzabyycdxx", new char[] {'z', 'a'} ) = 3
+ * StringUtils.indexOfAnyBut("aba", new char[] {'z'} ) = 0
+ * StringUtils.indexOfAnyBut("aba", new char[] {'a', 'b'} ) = -1
*
- *
+ *
* @param str the String to check, may be null
* @param searchChars the chars to search for, may be null
* @return the index of any of the chars, -1 if no match or null input
* @since 2.0
*/
- public static int indexOfAnyBut(String str, char[] searchChars) {
- if (str == null || str.length() == 0 || searchChars == null || searchChars.length == 0) {
- return -1;
- }
- outer: for (int i = 0; i < str.length(); i ++) {
- char ch = str.charAt(i);
- for (int j = 0; j < searchChars.length; j++) {
- if (searchChars[j] == ch) {
- continue outer;
- }
- }
- return i;
- }
- return -1;
- }
+ public static int indexOfAnyBut(String str, char[] searchChars) {
+ if (isEmpty(str) || ArrayUtils.isEmpty(searchChars)) {
+ return INDEX_NOT_FOUND;
+ }
+ int csLen = str.length();
+ int csLast = csLen - 1;
+ int searchLen = searchChars.length;
+ int searchLast = searchLen - 1;
+ outer:
+ for (int i = 0; i < csLen; i++) {
+ char ch = str.charAt(i);
+ for (int j = 0; j < searchLen; j++) {
+ if (searchChars[j] == ch) {
+ if (i < csLast && j < searchLast && CharUtils.isHighSurrogate(ch)) {
+ if (searchChars[j + 1] == str.charAt(i + 1)) {
+ continue outer;
+ }
+ } else {
+ continue outer;
+ }
+ }
+ }
+ return i;
+ }
+ return INDEX_NOT_FOUND;
+ }
/**
* Search a String to find the first index of any
* character not in the given set of characters.
*
* A null
String will return -1
.
- * A null
search string will return -1
.
- *
+ * A null
or empty search string will return -1
.
+ *
*
* StringUtils.indexOfAnyBut(null, *) = -1
* StringUtils.indexOfAnyBut("", *) = -1
* StringUtils.indexOfAnyBut(*, null) = -1
* StringUtils.indexOfAnyBut(*, "") = -1
* StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3
- * StringUtils.indexOfAnyBut("zzabyycdxx", "") = 0
+ * StringUtils.indexOfAnyBut("zzabyycdxx", "") = -1
* StringUtils.indexOfAnyBut("aba","ab") = -1
*
- *
+ *
* @param str the String to check, may be null
* @param searchChars the chars to search for, may be null
* @return the index of any of the chars, -1 if no match or null input
* @since 2.0
*/
public static int indexOfAnyBut(String str, String searchChars) {
- if (str == null || str.length() == 0 || searchChars == null || searchChars.length() == 0) {
- return -1;
+ if (isEmpty(str) || isEmpty(searchChars)) {
+ return INDEX_NOT_FOUND;
}
- for (int i = 0; i < str.length(); i++) {
- if (searchChars.indexOf(str.charAt(i)) < 0) {
- return i;
+ int strLen = str.length();
+ for (int i = 0; i < strLen; i++) {
+ char ch = str.charAt(i);
+ boolean chFound = searchChars.indexOf(ch) >= 0;
+ if (i + 1 < strLen && CharUtils.isHighSurrogate(ch)) {
+ char ch2 = str.charAt(i + 1);
+ if (chFound && searchChars.indexOf(ch2) < 0) {
+ return i;
+ }
+ } else {
+ if (!chFound) {
+ return i;
+ }
}
}
- return -1;
+ return INDEX_NOT_FOUND;
}
// ContainsOnly
@@ -1183,7 +1579,7 @@
*
* A null
String will return false
.
* A null
valid character array will return false
.
- * An empty String ("") always returns true
.
+ * An empty String (length()=0) always returns true
.
*
*
* StringUtils.containsOnly(null, *) = false
@@ -1194,14 +1590,14 @@
* StringUtils.containsOnly("ab1", 'abc') = false
* StringUtils.containsOnly("abz", 'abc') = false
*
- *
+ *
* @param str the String to check, may be null
* @param valid an array of valid chars, may be null
* @return true if it only contains valid chars and is non-null
*/
public static boolean containsOnly(String str, char[] valid) {
// All these pre-checks are to maintain API with an older version
- if ( (valid == null) || (str == null) ) {
+ if ((valid == null) || (str == null)) {
return false;
}
if (str.length() == 0) {
@@ -1210,15 +1606,15 @@
if (valid.length == 0) {
return false;
}
- return indexOfAnyBut(str, valid) == -1;
+ return indexOfAnyBut(str, valid) == INDEX_NOT_FOUND;
}
/**
* Checks if the String contains only certain characters.
*
* A null
String will return false
.
* A null
valid character String will return false
.
- * An empty String ("") always returns true
.
+ * An empty String (length()=0) always returns true
.
*
*
* StringUtils.containsOnly(null, *) = false
@@ -1229,7 +1625,7 @@
* StringUtils.containsOnly("ab1", "abc") = false
* StringUtils.containsOnly("abz", "abc") = false
*
- *
+ *
* @param str the String to check, may be null
* @param validChars a String of valid chars, may be null
* @return true if it only contains valid chars and is non-null
@@ -1241,15 +1637,15 @@
}
return containsOnly(str, validChars.toCharArray());
}
-
+
// ContainsNone
//-----------------------------------------------------------------------
/**
* Checks that the String does not contain certain characters.
*
* A null
String will return true
.
* A null
invalid character array will return true
.
- * An empty String ("") always returns true.
+ * An empty String (length()=0) always returns true.
*
*
* StringUtils.containsNone(null, *) = true
@@ -1260,23 +1656,36 @@
* StringUtils.containsNone("ab1", 'xyz') = true
* StringUtils.containsNone("abz", 'xyz') = false
*
- *
+ *
* @param str the String to check, may be null
- * @param invalidChars an array of invalid chars, may be null
+ * @param searchChars an array of invalid chars, may be null
* @return true if it contains none of the invalid chars, or is null
* @since 2.0
*/
- public static boolean containsNone(String str, char[] invalidChars) {
- if (str == null || invalidChars == null) {
+ public static boolean containsNone(String str, char[] searchChars) {
+ if (str == null || searchChars == null) {
return true;
}
- int strSize = str.length();
- int validSize = invalidChars.length;
- for (int i = 0; i < strSize; i++) {
+ int csLen = str.length();
+ int csLast = csLen - 1;
+ int searchLen = searchChars.length;
+ int searchLast = searchLen - 1;
+ for (int i = 0; i < csLen; i++) {
char ch = str.charAt(i);
- for (int j = 0; j < validSize; j++) {
- if (invalidChars[j] == ch) {
- return false;
+ for (int j = 0; j < searchLen; j++) {
+ if (searchChars[j] == ch) {
+ if (CharUtils.isHighSurrogate(ch)) {
+ if (j == searchLast) {
+ // missing low surrogate, fine, like String.indexOf(String)
+ return false;
+ }
+ if (i < csLast && searchChars[j + 1] == str.charAt(i + 1)) {
+ return false;
+ }
+ } else {
+ // ch is in the Basic Multilingual Plane
+ return false;
+ }
}
}
}
@@ -1299,7 +1708,7 @@
* StringUtils.containsNone("ab1", "xyz") = true
* StringUtils.containsNone("abz", "xyz") = false
*
- *
+ *
* @param str the String to check, may be null
* @param invalidChars a String of invalid chars, may be null
* @return true if it contains none of the invalid chars, or is null
@@ -1311,7 +1720,7 @@
}
return containsNone(str, invalidChars.toCharArray());
}
-
+
// IndexOfAny strings
//-----------------------------------------------------------------------
/**
@@ -1322,7 +1731,7 @@
* A null
search array entry will be ignored, but a search
* array containing "" will return 0
if str
is not
* null. This method uses {@link String#indexOf(String)}.
- *
+ *
*
* StringUtils.indexOfAny(null, *) = -1
* StringUtils.indexOfAny(*, null) = -1
@@ -1335,14 +1744,14 @@
* StringUtils.indexOfAny("", [""]) = 0
* StringUtils.indexOfAny("", ["a"]) = -1
*
- *
+ *
* @param str the String to check, may be null
* @param searchStrs the Strings to search for, may be null
* @return the first index of any of the searchStrs in str, -1 if no match
*/
public static int indexOfAny(String str, String[] searchStrs) {
if ((str == null) || (searchStrs == null)) {
- return -1;
+ return INDEX_NOT_FOUND;
}
int sz = searchStrs.length;
@@ -1356,7 +1765,7 @@
continue;
}
tmp = str.indexOf(search);
- if (tmp == -1) {
+ if (tmp == INDEX_NOT_FOUND) {
continue;
}
@@ -1365,7 +1774,7 @@
}
}
- return (ret == Integer.MAX_VALUE) ? -1 : ret;
+ return (ret == Integer.MAX_VALUE) ? INDEX_NOT_FOUND : ret;
}
/**
@@ -1374,9 +1783,9 @@
* A null
String will return -1
.
* A null
search array will return -1
.
* A null
or zero length search array entry will be ignored,
- * but a search array containing "" will return the length of str
+ * but a search array containing "" will return the length of str
* if str
is not null. This method uses {@link String#indexOf(String)}
- *
+ *
*
* StringUtils.lastIndexOfAny(null, *) = -1
* StringUtils.lastIndexOfAny(*, null) = -1
@@ -1388,17 +1797,17 @@
* StringUtils.lastIndexOfAny("zzabyycdxx", ["mn","op"]) = -1
* StringUtils.lastIndexOfAny("zzabyycdxx", ["mn",""]) = 10
*
- *
+ *
* @param str the String to check, may be null
* @param searchStrs the Strings to search for, may be null
* @return the last index of any of the Strings, -1 if no match
*/
public static int lastIndexOfAny(String str, String[] searchStrs) {
if ((str == null) || (searchStrs == null)) {
- return -1;
+ return INDEX_NOT_FOUND;
}
int sz = searchStrs.length;
- int ret = -1;
+ int ret = INDEX_NOT_FOUND;
int tmp = 0;
for (int i = 0; i < sz; i++) {
String search = searchStrs[i];
@@ -1423,7 +1832,7 @@
*
* A null
String will return null
.
* An empty ("") String will return "".
- *
+ *
*
* StringUtils.substring(null, *) = null
* StringUtils.substring("", *) = ""
@@ -1433,7 +1842,7 @@
* StringUtils.substring("abc", -2) = "bc"
* StringUtils.substring("abc", -4) = "abc"
*
- *
+ *
* @param str the String to get the substring from, may be null
* @param start the position to start from, negative means
* count back from the end of the String by this many characters
@@ -1458,22 +1867,22 @@
return str.substring(start);
}
-
+
/**
* Gets a substring from the specified String avoiding exceptions.
*
* A negative start position can be used to start/end n
* characters from the end of the String.
*
* The returned substring starts with the character in the start
- * position and ends before the end
position. All postion counting is
- * zero-based -- i.e., to start at the beginning of the string use
- * start = 0
. Negative start and end positions can be used to
+ * position and ends before the end
position. All position counting is
+ * zero-based -- i.e., to start at the beginning of the string use
+ * start = 0
. Negative start and end positions can be used to
* specify offsets relative to the end of the String.
*
* If start
is not strictly to the left of end
, ""
* is returned.
- *
+ *
*
* StringUtils.substring(null, *, *) = null
* StringUtils.substring("", * , *) = "";
@@ -1485,7 +1894,7 @@
* StringUtils.substring("abc", -2, -1) = "b"
* StringUtils.substring("abc", -4, 2) = "ab"
*
- *
+ *
* @param str the String to get the substring from, may be null
* @param start the position to start from, negative means
* count back from the end of the String by this many characters
@@ -1534,7 +1943,7 @@
*
* If len
characters are not available, or the
* String is null
, the String will be returned without
- * an exception. An exception is thrown if len is negative.
+ * an exception. An empty String is returned if len is negative.
*
*
* StringUtils.left(null, *) = null
@@ -1544,9 +1953,9 @@
* StringUtils.left("abc", 2) = "ab"
* StringUtils.left("abc", 4) = "abc"
*
- *
+ *
* @param str the String to get the leftmost characters from, may be null
- * @param len the length of the required String, must be zero or positive
+ * @param len the length of the required String
* @return the leftmost characters, null
if null String input
*/
public static String left(String str, int len) {
@@ -1558,17 +1967,16 @@
}
if (str.length() <= len) {
return str;
- } else {
- return str.substring(0, len);
}
+ return str.substring(0, len);
}
/**
* Gets the rightmost len
characters of a String.
*
* If len
characters are not available, or the String
* is null
, the String will be returned without an
- * an exception. An exception is thrown if len is negative.
+ * an exception. An empty String is returned if len is negative.
*
*
* StringUtils.right(null, *) = null
@@ -1578,9 +1986,9 @@
* StringUtils.right("abc", 2) = "bc"
* StringUtils.right("abc", 4) = "abc"
*
- *
+ *
* @param str the String to get the rightmost characters from, may be null
- * @param len the length of the required String, must be zero or positive
+ * @param len the length of the required String
* @return the rightmost characters, null
if null String input
*/
public static String right(String str, int len) {
@@ -1592,9 +2000,8 @@
}
if (str.length() <= len) {
return str;
- } else {
- return str.substring(str.length() - len);
}
+ return str.substring(str.length() - len);
}
/**
@@ -1603,7 +2010,8 @@
* If len
characters are not available, the remainder
* of the String will be returned without an exception. If the
* String is null
, null
will be returned.
- * An exception is thrown if len is negative.
+ * An empty String is returned if len is negative or exceeds the
+ * length of str
.
*
*
* StringUtils.mid(null, *, *) = null
@@ -1615,10 +2023,10 @@
* StringUtils.mid("abc", 4, 2) = ""
* StringUtils.mid("abc", -2, 2) = "ab"
*
- *
+ *
* @param str the String to get the characters from, may be null
* @param pos the position to start from, negative treated as zero
- * @param len the length of the required String, must be zero or positive
+ * @param len the length of the required String
* @return the middle characters, null
if null String input
*/
public static String mid(String str, int pos, int len) {
@@ -1633,21 +2041,22 @@
}
if (str.length() <= (pos + len)) {
return str.substring(pos);
- } else {
- return str.substring(pos, pos + len);
}
+ return str.substring(pos, pos + len);
}
// SubStringAfter/SubStringBefore
//-----------------------------------------------------------------------
/**
- * Gets the substring before the first occurance of a separator.
+ *
Gets the substring before the first occurrence of a separator.
* The separator is not returned.
*
* A null
string input will return null
.
* An empty ("") string input will return the empty string.
* A null
separator will return the input string.
*
+ * If nothing is found, the string input is returned.
+ *
*
* StringUtils.substringBefore(null, *) = null
* StringUtils.substringBefore("", *) = ""
@@ -1661,33 +2070,35 @@
*
* @param str the String to get a substring from, may be null
* @param separator the String to search for, may be null
- * @return the substring before the first occurance of the separator,
+ * @return the substring before the first occurrence of the separator,
* null
if null String input
* @since 2.0
*/
public static String substringBefore(String str, String separator) {
- if (str == null || separator == null || str.length() == 0) {
+ if (isEmpty(str) || separator == null) {
return str;
}
if (separator.length() == 0) {
return EMPTY;
}
int pos = str.indexOf(separator);
- if (pos == -1) {
+ if (pos == INDEX_NOT_FOUND) {
return str;
}
return str.substring(0, pos);
}
/**
- * Gets the substring after the first occurance of a separator.
+ *
Gets the substring after the first occurrence of a separator.
* The separator is not returned.
*
* A null
string input will return null
.
* An empty ("") string input will return the empty string.
* A null
separator will return the empty string if the
* input string is not null
.
- *
+ *
+ * If nothing is found, the empty string is returned.
+ *
*
* StringUtils.substringAfter(null, *) = null
* StringUtils.substringAfter("", *) = ""
@@ -1701,32 +2112,34 @@
*
* @param str the String to get a substring from, may be null
* @param separator the String to search for, may be null
- * @return the substring after the first occurance of the separator,
+ * @return the substring after the first occurrence of the separator,
* null
if null String input
* @since 2.0
*/
public static String substringAfter(String str, String separator) {
- if (str == null || str.length() == 0) {
+ if (isEmpty(str)) {
return str;
}
if (separator == null) {
return EMPTY;
}
int pos = str.indexOf(separator);
- if (pos == -1) {
+ if (pos == INDEX_NOT_FOUND) {
return EMPTY;
}
return str.substring(pos + separator.length());
}
/**
- * Gets the substring before the last occurance of a separator.
+ *
Gets the substring before the last occurrence of a separator.
* The separator is not returned.
*
* A null
string input will return null
.
* An empty ("") string input will return the empty string.
* An empty or null
separator will return the input string.
- *
+ *
+ * If nothing is found, the string input is returned.
+ *
*
* StringUtils.substringBeforeLast(null, *) = null
* StringUtils.substringBeforeLast("", *) = ""
@@ -1740,30 +2153,32 @@
*
* @param str the String to get a substring from, may be null
* @param separator the String to search for, may be null
- * @return the substring before the last occurance of the separator,
+ * @return the substring before the last occurrence of the separator,
* null
if null String input
* @since 2.0
*/
public static String substringBeforeLast(String str, String separator) {
- if (str == null || separator == null || str.length() == 0 || separator.length() == 0) {
+ if (isEmpty(str) || isEmpty(separator)) {
return str;
}
int pos = str.lastIndexOf(separator);
- if (pos == -1) {
+ if (pos == INDEX_NOT_FOUND) {
return str;
}
return str.substring(0, pos);
}
/**
- * Gets the substring after the last occurance of a separator.
+ *
Gets the substring after the last occurrence of a separator.
* The separator is not returned.
*
* A null
string input will return null
.
* An empty ("") string input will return the empty string.
* An empty or null
separator will return the empty string if
* the input string is not null
.
*
+ * If nothing is found, the empty string is returned.
+ *
*
* StringUtils.substringAfterLast(null, *) = null
* StringUtils.substringAfterLast("", *) = ""
@@ -1778,19 +2193,19 @@
*
* @param str the String to get a substring from, may be null
* @param separator the String to search for, may be null
- * @return the substring after the last occurance of the separator,
+ * @return the substring after the last occurrence of the separator,
* null
if null String input
* @since 2.0
*/
public static String substringAfterLast(String str, String separator) {
- if (str == null || str.length() == 0) {
+ if (isEmpty(str)) {
return str;
}
- if (separator == null || separator.length() == 0) {
+ if (isEmpty(separator)) {
return EMPTY;
}
int pos = str.lastIndexOf(separator);
- if (pos == -1 || pos == (str.length() - separator.length())) {
+ if (pos == INDEX_NOT_FOUND || pos == (str.length() - separator.length())) {
return EMPTY;
}
return str.substring(pos + separator.length());
@@ -1804,7 +2219,7 @@
*
* A null
input String returns null
.
* A null
tag returns null
.
- *
+ *
*
* StringUtils.substringBetween(null, *) = null
* StringUtils.substringBetween("", "") = ""
@@ -1822,21 +2237,23 @@
public static String substringBetween(String str, String tag) {
return substringBetween(str, tag, tag);
}
-
+
/**
* Gets the String that is nested in between two Strings.
* Only the first match is returned.
- *
+ *
* A null
input String returns null
.
* A null
open/close returns null
(no match).
- * An empty ("") open/close returns an empty string.
+ * An empty ("") open and close returns an empty string.
*
*
+ * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b"
* StringUtils.substringBetween(null, *, *) = null
+ * StringUtils.substringBetween(*, null, *) = null
+ * StringUtils.substringBetween(*, *, null) = null
* StringUtils.substringBetween("", "", "") = ""
- * StringUtils.substringBetween("", "", "tag") = null
- * StringUtils.substringBetween("", "tag", "tag") = null
- * StringUtils.substringBetween("yabcz", null, null) = null
+ * StringUtils.substringBetween("", "", "]") = null
+ * StringUtils.substringBetween("", "[", "]") = null
* StringUtils.substringBetween("yabcz", "", "") = ""
* StringUtils.substringBetween("yabcz", "y", "z") = "abc"
* StringUtils.substringBetween("yabczyabcz", "y", "z") = "abc"
@@ -1853,15 +2270,68 @@
return null;
}
int start = str.indexOf(open);
- if (start != -1) {
+ if (start != INDEX_NOT_FOUND) {
int end = str.indexOf(close, start + open.length());
- if (end != -1) {
+ if (end != INDEX_NOT_FOUND) {
return str.substring(start + open.length(), end);
}
}
return null;
}
+ /**
+ * Searches a String for substrings delimited by a start and end tag,
+ * returning all matching substrings in an array.
+ *
+ * A null
input String returns null
.
+ * A null
open/close returns null
(no match).
+ * An empty ("") open/close returns null
(no match).
+ *
+ *
+ * StringUtils.substringsBetween("[a][b][c]", "[", "]") = ["a","b","c"]
+ * StringUtils.substringsBetween(null, *, *) = null
+ * StringUtils.substringsBetween(*, null, *) = null
+ * StringUtils.substringsBetween(*, *, null) = null
+ * StringUtils.substringsBetween("", "[", "]") = []
+ *
+ *
+ * @param str the String containing the substrings, null returns null, empty returns empty
+ * @param open the String identifying the start of the substring, empty returns null
+ * @param close the String identifying the end of the substring, empty returns null
+ * @return a String Array of substrings, or null
if no match
+ * @since 2.3
+ */
+ public static String[] substringsBetween(String str, String open, String close) {
+ if (str == null || isEmpty(open) || isEmpty(close)) {
+ return null;
+ }
+ int strLen = str.length();
+ if (strLen == 0) {
+ return ArrayUtils.EMPTY_STRING_ARRAY;
+ }
+ int closeLen = close.length();
+ int openLen = open.length();
+ List list = new ArrayList();
+ int pos = 0;
+ while (pos < (strLen - closeLen)) {
+ int start = str.indexOf(open, pos);
+ if (start < 0) {
+ break;
+ }
+ start += openLen;
+ int end = str.indexOf(close, start);
+ if (end < 0) {
+ break;
+ }
+ list.add(str.substring(start, end));
+ pos = end + closeLen;
+ }
+ if (list.isEmpty()) {
+ return null;
+ }
+ return (String[]) list.toArray(new String [list.size()]);
+ }
+
// Nested extraction
//-----------------------------------------------------------------------
/**
@@ -1870,7 +2340,7 @@
*
* A null
input String returns null
.
* A null
tag returns null
.
- *
+ *
*
* StringUtils.getNestedString(null, *) = null
* StringUtils.getNestedString("", "") = ""
@@ -1889,11 +2359,11 @@
public static String getNestedString(String str, String tag) {
return substringBetween(str, tag, tag);
}
-
+
/**
* Gets the String that is nested in between two Strings.
* Only the first match is returned.
- *
+ *
* A null
input String returns null
.
* A null
open/close returns null
(no match).
* An empty ("") open/close returns an empty string.
@@ -1928,8 +2398,9 @@
* Whitespace is defined by {@link Character#isWhitespace(char)}.
*
* The separator is not included in the returned String array.
- * Adjacent separators are treated as one separator.
- *
+ * Adjacent separators are treated as one separator.
+ * For more control over the split use the StrTokenizer class.
+ *
* A null
input String returns null
.
*
*
@@ -1939,7 +2410,7 @@
* StringUtils.split("abc def") = ["abc", "def"]
* StringUtils.split(" abc ") = ["abc"]
*
- *
+ *
* @param str the String to parse, may be null
* @return an array of parsed Strings, null
if null String input
*/
@@ -1952,8 +2423,9 @@
* This is an alternative to using StringTokenizer.
*
* The separator is not included in the returned String array.
- * Adjacent separators are treated as one separator.
- *
+ * Adjacent separators are treated as one separator.
+ * For more control over the split use the StrTokenizer class.
+ *
* A null
input String returns null
.
*
*
@@ -1962,19 +2434,362 @@
* StringUtils.split("a.b.c", '.') = ["a", "b", "c"]
* StringUtils.split("a..b.c", '.') = ["a", "b", "c"]
* StringUtils.split("a:b:c", '.') = ["a:b:c"]
- * StringUtils.split("a\tb\nc", null) = ["a", "b", "c"]
* StringUtils.split("a b c", ' ') = ["a", "b", "c"]
*
- *
+ *
* @param str the String to parse, may be null
- * @param separatorChar the character used as the delimiter,
- * null
splits on whitespace
+ * @param separatorChar the character used as the delimiter
* @return an array of parsed Strings, null
if null String input
* @since 2.0
*/
public static String[] split(String str, char separatorChar) {
+ return splitWorker(str, separatorChar, false);
+ }
+
+ /**
+ * Splits the provided text into an array, separators specified.
+ * This is an alternative to using StringTokenizer.
+ *
+ * The separator is not included in the returned String array.
+ * Adjacent separators are treated as one separator.
+ * For more control over the split use the StrTokenizer class.
+ *
+ * A null
input String returns null
.
+ * A null
separatorChars splits on whitespace.
+ *
+ *
+ * StringUtils.split(null, *) = null
+ * StringUtils.split("", *) = []
+ * StringUtils.split("abc def", null) = ["abc", "def"]
+ * StringUtils.split("abc def", " ") = ["abc", "def"]
+ * StringUtils.split("abc def", " ") = ["abc", "def"]
+ * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"]
+ *
+ *
+ * @param str the String to parse, may be null
+ * @param separatorChars the characters used as the delimiters,
+ * null
splits on whitespace
+ * @return an array of parsed Strings, null
if null String input
+ */
+ public static String[] split(String str, String separatorChars) {
+ return splitWorker(str, separatorChars, -1, false);
+ }
+
+ /**
+ * Splits the provided text into an array with a maximum length,
+ * separators specified.
+ *
+ * The separator is not included in the returned String array.
+ * Adjacent separators are treated as one separator.
+ *
+ * A null
input String returns null
.
+ * A null
separatorChars splits on whitespace.
+ *
+ * If more than max
delimited substrings are found, the last
+ * returned string includes all characters after the first max - 1
+ * returned strings (including separator characters).
+ *
+ *
+ * StringUtils.split(null, *, *) = null
+ * StringUtils.split("", *, *) = []
+ * StringUtils.split("ab de fg", null, 0) = ["ab", "cd", "ef"]
+ * StringUtils.split("ab de fg", null, 0) = ["ab", "cd", "ef"]
+ * StringUtils.split("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"]
+ * StringUtils.split("ab:cd:ef", ":", 2) = ["ab", "cd:ef"]
+ *
+ *
+ * @param str the String to parse, may be null
+ * @param separatorChars the characters used as the delimiters,
+ * null
splits on whitespace
+ * @param max the maximum number of elements to include in the
+ * array. A zero or negative value implies no limit
+ * @return an array of parsed Strings, null
if null String input
+ */
+ public static String[] split(String str, String separatorChars, int max) {
+ return splitWorker(str, separatorChars, max, false);
+ }
+
+ /**
+ * Splits the provided text into an array, separator string specified.
+ *
+ * The separator(s) will not be included in the returned String array.
+ * Adjacent separators are treated as one separator.
+ *
+ * A null
input String returns null
.
+ * A null
separator splits on whitespace.
+ *
+ *
+ * StringUtils.splitByWholeSeparator(null, *) = null
+ * StringUtils.splitByWholeSeparator("", *) = []
+ * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"]
+ * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"]
+ * StringUtils.splitByWholeSeparator("ab:cd:ef", ":") = ["ab", "cd", "ef"]
+ * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
+ *
+ *
+ * @param str the String to parse, may be null
+ * @param separator String containing the String to be used as a delimiter,
+ * null
splits on whitespace
+ * @return an array of parsed Strings, null
if null String was input
+ */
+ public static String[] splitByWholeSeparator(String str, String separator) {
+ return splitByWholeSeparatorWorker( str, separator, -1, false ) ;
+ }
+
+ /**
+ * Splits the provided text into an array, separator string specified.
+ * Returns a maximum of max
substrings.
+ *
+ * The separator(s) will not be included in the returned String array.
+ * Adjacent separators are treated as one separator.
+ *
+ * A null
input String returns null
.
+ * A null
separator splits on whitespace.
+ *
+ *
+ * StringUtils.splitByWholeSeparator(null, *, *) = null
+ * StringUtils.splitByWholeSeparator("", *, *) = []
+ * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"]
+ * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"]
+ * StringUtils.splitByWholeSeparator("ab:cd:ef", ":", 2) = ["ab", "cd:ef"]
+ * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
+ * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
+ *
+ *
+ * @param str the String to parse, may be null
+ * @param separator String containing the String to be used as a delimiter,
+ * null
splits on whitespace
+ * @param max the maximum number of elements to include in the returned
+ * array. A zero or negative value implies no limit.
+ * @return an array of parsed Strings, null
if null String was input
+ */
+ public static String[] splitByWholeSeparator( String str, String separator, int max ) {
+ return splitByWholeSeparatorWorker(str, separator, max, false);
+ }
+
+ /**
+ * Splits the provided text into an array, separator string specified.
+ *
+ * The separator is not included in the returned String array.
+ * Adjacent separators are treated as separators for empty tokens.
+ * For more control over the split use the StrTokenizer class.
+ *
+ * A null
input String returns null
.
+ * A null
separator splits on whitespace.
+ *
+ *
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *) = null
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *) = []
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null) = ["ab", "de", "fg"]
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null) = ["ab", "", "", "de", "fg"]
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"]
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
+ *
+ *
+ * @param str the String to parse, may be null
+ * @param separator String containing the String to be used as a delimiter,
+ * null
splits on whitespace
+ * @return an array of parsed Strings, null
if null String was input
+ * @since 2.4
+ */
+ public static String[] splitByWholeSeparatorPreserveAllTokens(String str, String separator) {
+ return splitByWholeSeparatorWorker(str, separator, -1, true);
+ }
+
+ /**
+ * Splits the provided text into an array, separator string specified.
+ * Returns a maximum of max
substrings.
+ *
+ * The separator is not included in the returned String array.
+ * Adjacent separators are treated as separators for empty tokens.
+ * For more control over the split use the StrTokenizer class.
+ *
+ * A null
input String returns null
.
+ * A null
separator splits on whitespace.
+ *
+ *
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *, *) = null
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *, *) = []
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0) = ["ab", "de", "fg"]
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0) = ["ab", "", "", "de", "fg"]
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"]
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
+ *
+ *
+ * @param str the String to parse, may be null
+ * @param separator String containing the String to be used as a delimiter,
+ * null
splits on whitespace
+ * @param max the maximum number of elements to include in the returned
+ * array. A zero or negative value implies no limit.
+ * @return an array of parsed Strings, null
if null String was input
+ * @since 2.4
+ */
+ public static String[] splitByWholeSeparatorPreserveAllTokens(String str, String separator, int max) {
+ return splitByWholeSeparatorWorker(str, separator, max, true);
+ }
+
+ /**
+ * Performs the logic for the splitByWholeSeparatorPreserveAllTokens
methods.
+ *
+ * @param str the String to parse, may be null
+ * @param separator String containing the String to be used as a delimiter,
+ * null
splits on whitespace
+ * @param max the maximum number of elements to include in the returned
+ * array. A zero or negative value implies no limit.
+ * @param preserveAllTokens if true
, adjacent separators are
+ * treated as empty token separators; if false
, adjacent
+ * separators are treated as one separator.
+ * @return an array of parsed Strings, null
if null String input
+ * @since 2.4
+ */
+ private static String[] splitByWholeSeparatorWorker(String str, String separator, int max,
+ boolean preserveAllTokens)
+ {
+ if (str == null) {
+ return null;
+ }
+
+ int len = str.length();
+
+ if (len == 0) {
+ return ArrayUtils.EMPTY_STRING_ARRAY;
+ }
+
+ if ((separator == null) || (EMPTY.equals(separator))) {
+ // Split on whitespace.
+ return splitWorker(str, null, max, preserveAllTokens);
+ }
+
+ int separatorLength = separator.length();
+
+ ArrayList substrings = new ArrayList();
+ int numberOfSubstrings = 0;
+ int beg = 0;
+ int end = 0;
+ while (end < len) {
+ end = str.indexOf(separator, beg);
+
+ if (end > -1) {
+ if (end > beg) {
+ numberOfSubstrings += 1;
+
+ if (numberOfSubstrings == max) {
+ end = len;
+ substrings.add(str.substring(beg));
+ } else {
+ // The following is OK, because String.substring( beg, end ) excludes
+ // the character at the position 'end'.
+ substrings.add(str.substring(beg, end));
+
+ // Set the starting point for the next search.
+ // The following is equivalent to beg = end + (separatorLength - 1) + 1,
+ // which is the right calculation:
+ beg = end + separatorLength;
+ }
+ } else {
+ // We found a consecutive occurrence of the separator, so skip it.
+ if (preserveAllTokens) {
+ numberOfSubstrings += 1;
+ if (numberOfSubstrings == max) {
+ end = len;
+ substrings.add(str.substring(beg));
+ } else {
+ substrings.add(EMPTY);
+ }
+ }
+ beg = end + separatorLength;
+ }
+ } else {
+ // String.substring( beg ) goes from 'beg' to the end of the String.
+ substrings.add(str.substring(beg));
+ end = len;
+ }
+ }
+
+ return (String[]) substrings.toArray(new String[substrings.size()]);
+ }
+
+ // -----------------------------------------------------------------------
+ /**
+ * Splits the provided text into an array, using whitespace as the
+ * separator, preserving all tokens, including empty tokens created by
+ * adjacent separators. This is an alternative to using StringTokenizer.
+ * Whitespace is defined by {@link Character#isWhitespace(char)}.
+ *
+ * The separator is not included in the returned String array.
+ * Adjacent separators are treated as separators for empty tokens.
+ * For more control over the split use the StrTokenizer class.
+ *
+ * A null
input String returns null
.
+ *
+ *
+ * StringUtils.splitPreserveAllTokens(null) = null
+ * StringUtils.splitPreserveAllTokens("") = []
+ * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "def"]
+ * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "", "def"]
+ * StringUtils.splitPreserveAllTokens(" abc ") = ["", "abc", ""]
+ *
+ *
+ * @param str the String to parse, may be null
+ * @return an array of parsed Strings, null
if null String input
+ * @since 2.1
+ */
+ public static String[] splitPreserveAllTokens(String str) {
+ return splitWorker(str, null, -1, true);
+ }
+
+ /**
+ * Splits the provided text into an array, separator specified,
+ * preserving all tokens, including empty tokens created by adjacent
+ * separators. This is an alternative to using StringTokenizer.
+ *
+ * The separator is not included in the returned String array.
+ * Adjacent separators are treated as separators for empty tokens.
+ * For more control over the split use the StrTokenizer class.
+ *
+ * A null
input String returns null
.
+ *
+ *
+ * StringUtils.splitPreserveAllTokens(null, *) = null
+ * StringUtils.splitPreserveAllTokens("", *) = []
+ * StringUtils.splitPreserveAllTokens("a.b.c", '.') = ["a", "b", "c"]
+ * StringUtils.splitPreserveAllTokens("a..b.c", '.') = ["a", "", "b", "c"]
+ * StringUtils.splitPreserveAllTokens("a:b:c", '.') = ["a:b:c"]
+ * StringUtils.splitPreserveAllTokens("a\tb\nc", null) = ["a", "b", "c"]
+ * StringUtils.splitPreserveAllTokens("a b c", ' ') = ["a", "b", "c"]
+ * StringUtils.splitPreserveAllTokens("a b c ", ' ') = ["a", "b", "c", ""]
+ * StringUtils.splitPreserveAllTokens("a b c ", ' ') = ["a", "b", "c", "", ""]
+ * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", a", "b", "c"]
+ * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", "", a", "b", "c"]
+ * StringUtils.splitPreserveAllTokens(" a b c ", ' ') = ["", a", "b", "c", ""]
+ *
+ *
+ * @param str the String to parse, may be null
+ * @param separatorChar the character used as the delimiter,
+ * null
splits on whitespace
+ * @return an array of parsed Strings, null
if null String input
+ * @since 2.1
+ */
+ public static String[] splitPreserveAllTokens(String str, char separatorChar) {
+ return splitWorker(str, separatorChar, true);
+ }
+
+ /**
+ * Performs the logic for the split
and
+ * splitPreserveAllTokens
methods that do not return a
+ * maximum array length.
+ *
+ * @param str the String to parse, may be null
+ * @param separatorChar the separate character
+ * @param preserveAllTokens if true
, adjacent separators are
+ * treated as empty token separators; if false
, adjacent
+ * separators are treated as one separator.
+ * @return an array of parsed Strings, null
if null String input
+ */
+ private static String[] splitWorker(String str, char separatorChar, boolean preserveAllTokens) {
// Performance tuned for 2.0 (JDK1.4)
-
+
if (str == null) {
return null;
}
@@ -1983,85 +2798,125 @@
return ArrayUtils.EMPTY_STRING_ARRAY;
}
List list = new ArrayList();
- int i =0, start = 0;
+ int i = 0, start = 0;
boolean match = false;
+ boolean lastMatch = false;
while (i < len) {
if (str.charAt(i) == separatorChar) {
- if (match) {
+ if (match || preserveAllTokens) {
list.add(str.substring(start, i));
match = false;
+ lastMatch = true;
}
start = ++i;
continue;
}
+ lastMatch = false;
match = true;
i++;
}
- if (match) {
+ if (match || (preserveAllTokens && lastMatch)) {
list.add(str.substring(start, i));
}
return (String[]) list.toArray(new String[list.size()]);
}
/**
- * Splits the provided text into an array, separators specified.
- * This is an alternative to using StringTokenizer.
+ * Splits the provided text into an array, separators specified,
+ * preserving all tokens, including empty tokens created by adjacent
+ * separators. This is an alternative to using StringTokenizer.
*
* The separator is not included in the returned String array.
- * Adjacent separators are treated as one separator.
- *
+ * Adjacent separators are treated as separators for empty tokens.
+ * For more control over the split use the StrTokenizer class.
+ *
* A null
input String returns null
.
* A null
separatorChars splits on whitespace.
*
*
- * StringUtils.split(null, *) = null
- * StringUtils.split("", *) = []
- * StringUtils.split("abc def", null) = ["abc", "def"]
- * StringUtils.split("abc def", " ") = ["abc", "def"]
- * StringUtils.split("abc def", " ") = ["abc", "def"]
- * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"]
+ * StringUtils.splitPreserveAllTokens(null, *) = null
+ * StringUtils.splitPreserveAllTokens("", *) = []
+ * StringUtils.splitPreserveAllTokens("abc def", null) = ["abc", "def"]
+ * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "def"]
+ * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "", def"]
+ * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"]
+ * StringUtils.splitPreserveAllTokens("ab:cd:ef:", ":") = ["ab", "cd", "ef", ""]
+ * StringUtils.splitPreserveAllTokens("ab:cd:ef::", ":") = ["ab", "cd", "ef", "", ""]
+ * StringUtils.splitPreserveAllTokens("ab::cd:ef", ":") = ["ab", "", cd", "ef"]
+ * StringUtils.splitPreserveAllTokens(":cd:ef", ":") = ["", cd", "ef"]
+ * StringUtils.splitPreserveAllTokens("::cd:ef", ":") = ["", "", cd", "ef"]
+ * StringUtils.splitPreserveAllTokens(":cd:ef:", ":") = ["", cd", "ef", ""]
*
- *
- * @param str the String to parse, may be null
+ *
+ * @param str the String to parse, may be null
* @param separatorChars the characters used as the delimiters,
* null
splits on whitespace
* @return an array of parsed Strings, null
if null String input
+ * @since 2.1
*/
- public static String[] split(String str, String separatorChars) {
- return split(str, separatorChars, -1);
+ public static String[] splitPreserveAllTokens(String str, String separatorChars) {
+ return splitWorker(str, separatorChars, -1, true);
}
/**
- * Splits the provided text into an array, separators specified.
- * This is an alternative to using StringTokenizer.
+ * Splits the provided text into an array with a maximum length,
+ * separators specified, preserving all tokens, including empty tokens
+ * created by adjacent separators.
*
* The separator is not included in the returned String array.
+ * Adjacent separators are treated as separators for empty tokens.
* Adjacent separators are treated as one separator.
*
* A null
input String returns null
.
* A null
separatorChars splits on whitespace.
- *
+ *
+ * If more than max
delimited substrings are found, the last
+ * returned string includes all characters after the first max - 1
+ * returned strings (including separator characters).
+ *
*
- * StringUtils.split(null, *, *) = null
- * StringUtils.split("", *, *) = []
- * StringUtils.split("ab de fg", null, 0) = ["ab", "cd", "ef"]
- * StringUtils.split("ab de fg", null, 0) = ["ab", "cd", "ef"]
- * StringUtils.split("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"]
- * StringUtils.split("ab:cd:ef", ":", 2) = ["ab", "cdef"]
+ * StringUtils.splitPreserveAllTokens(null, *, *) = null
+ * StringUtils.splitPreserveAllTokens("", *, *) = []
+ * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "cd", "ef"]
+ * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "cd", "ef"]
+ * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"]
+ * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"]
+ * StringUtils.splitPreserveAllTokens("ab de fg", null, 2) = ["ab", " de fg"]
+ * StringUtils.splitPreserveAllTokens("ab de fg", null, 3) = ["ab", "", " de fg"]
+ * StringUtils.splitPreserveAllTokens("ab de fg", null, 4) = ["ab", "", "", "de fg"]
*
- *
- * @param str the String to parse, may be null
+ *
+ * @param str the String to parse, may be null
* @param separatorChars the characters used as the delimiters,
* null
splits on whitespace
* @param max the maximum number of elements to include in the
* array. A zero or negative value implies no limit
* @return an array of parsed Strings, null
if null String input
+ * @since 2.1
*/
- public static String[] split(String str, String separatorChars, int max) {
+ public static String[] splitPreserveAllTokens(String str, String separatorChars, int max) {
+ return splitWorker(str, separatorChars, max, true);
+ }
+
+ /**
+ * Performs the logic for the split
and
+ * splitPreserveAllTokens
methods that return a maximum array
+ * length.
+ *
+ * @param str the String to parse, may be null
+ * @param separatorChars the separate character
+ * @param max the maximum number of elements to include in the
+ * array. A zero or negative value implies no limit.
+ * @param preserveAllTokens if true
, adjacent separators are
+ * treated as empty token separators; if false
, adjacent
+ * separators are treated as one separator.
+ * @return an array of parsed Strings, null
if null String input
+ */
+ private static String[] splitWorker(String str, String separatorChars, int max, boolean preserveAllTokens) {
// Performance tuned for 2.0 (JDK1.4)
// Direct code is quicker than StringTokenizer.
// Also, StringTokenizer uses isSpace() not isWhitespace()
-
+
if (str == null) {
return null;
}
@@ -2071,22 +2926,26 @@
}
List list = new ArrayList();
int sizePlus1 = 1;
- int i =0, start = 0;
+ int i = 0, start = 0;
boolean match = false;
+ boolean lastMatch = false;
if (separatorChars == null) {
// Null separator means use whitespace
while (i < len) {
if (Character.isWhitespace(str.charAt(i))) {
- if (match) {
+ if (match || preserveAllTokens) {
+ lastMatch = true;
if (sizePlus1++ == max) {
i = len;
+ lastMatch = false;
}
list.add(str.substring(start, i));
match = false;
}
start = ++i;
continue;
}
+ lastMatch = false;
match = true;
i++;
}
@@ -2095,48 +2954,153 @@
char sep = separatorChars.charAt(0);
while (i < len) {
if (str.charAt(i) == sep) {
- if (match) {
+ if (match || preserveAllTokens) {
+ lastMatch = true;
if (sizePlus1++ == max) {
i = len;
+ lastMatch = false;
}
list.add(str.substring(start, i));
match = false;
}
start = ++i;
continue;
}
+ lastMatch = false;
match = true;
i++;
}
} else {
// standard case
while (i < len) {
if (separatorChars.indexOf(str.charAt(i)) >= 0) {
- if (match) {
+ if (match || preserveAllTokens) {
+ lastMatch = true;
if (sizePlus1++ == max) {
i = len;
+ lastMatch = false;
}
list.add(str.substring(start, i));
match = false;
}
start = ++i;
continue;
}
+ lastMatch = false;
match = true;
i++;
}
}
- if (match) {
+ if (match || (preserveAllTokens && lastMatch)) {
list.add(str.substring(start, i));
}
return (String[]) list.toArray(new String[list.size()]);
}
+ /**
+ * Splits a String by Character type as returned by
+ * java.lang.Character.getType(char)
. Groups of contiguous
+ * characters of the same type are returned as complete tokens.
+ *
+ * StringUtils.splitByCharacterType(null) = null
+ * StringUtils.splitByCharacterType("") = []
+ * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"]
+ * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"]
+ * StringUtils.splitByCharacterType("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"]
+ * StringUtils.splitByCharacterType("number5") = ["number", "5"]
+ * StringUtils.splitByCharacterType("fooBar") = ["foo", "B", "ar"]
+ * StringUtils.splitByCharacterType("foo200Bar") = ["foo", "200", "B", "ar"]
+ * StringUtils.splitByCharacterType("ASFRules") = ["ASFR", "ules"]
+ *
+ * @param str the String to split, may be null
+ * @return an array of parsed Strings, null
if null String input
+ * @since 2.4
+ */
+ public static String[] splitByCharacterType(String str) {
+ return splitByCharacterType(str, false);
+ }
+
+ /**
+ * Splits a String by Character type as returned by
+ * java.lang.Character.getType(char)
. Groups of contiguous
+ * characters of the same type are returned as complete tokens, with the
+ * following exception: the character of type
+ * Character.UPPERCASE_LETTER
, if any, immediately
+ * preceding a token of type Character.LOWERCASE_LETTER
+ * will belong to the following token rather than to the preceding, if any,
+ * Character.UPPERCASE_LETTER
token.
+ *
+ * StringUtils.splitByCharacterTypeCamelCase(null) = null
+ * StringUtils.splitByCharacterTypeCamelCase("") = []
+ * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"]
+ * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"]
+ * StringUtils.splitByCharacterTypeCamelCase("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"]
+ * StringUtils.splitByCharacterTypeCamelCase("number5") = ["number", "5"]
+ * StringUtils.splitByCharacterTypeCamelCase("fooBar") = ["foo", "Bar"]
+ * StringUtils.splitByCharacterTypeCamelCase("foo200Bar") = ["foo", "200", "Bar"]
+ * StringUtils.splitByCharacterTypeCamelCase("ASFRules") = ["ASF", "Rules"]
+ *
+ * @param str the String to split, may be null
+ * @return an array of parsed Strings, null
if null String input
+ * @since 2.4
+ */
+ public static String[] splitByCharacterTypeCamelCase(String str) {
+ return splitByCharacterType(str, true);
+ }
+
+ /**
+ * Splits a String by Character type as returned by
+ * java.lang.Character.getType(char)
. Groups of contiguous
+ * characters of the same type are returned as complete tokens, with the
+ * following exception: if camelCase
is true
,
+ * the character of type Character.UPPERCASE_LETTER
, if any,
+ * immediately preceding a token of type Character.LOWERCASE_LETTER
+ * will belong to the following token rather than to the preceding, if any,
+ * Character.UPPERCASE_LETTER
token.
+ * @param str the String to split, may be null
+ * @param camelCase whether to use so-called "camel-case" for letter types
+ * @return an array of parsed Strings, null
if null String input
+ * @since 2.4
+ */
+ private static String[] splitByCharacterType(String str, boolean camelCase) {
+ if (str == null) {
+ return null;
+ }
+ if (str.length() == 0) {
+ return ArrayUtils.EMPTY_STRING_ARRAY;
+ }
+ char[] c = str.toCharArray();
+ List list = new ArrayList();
+ int tokenStart = 0;
+ int currentType = Character.getType(c[tokenStart]);
+ for (int pos = tokenStart + 1; pos < c.length; pos++) {
+ int type = Character.getType(c[pos]);
+ if (type == currentType) {
+ continue;
+ }
+ if (camelCase && type == Character.LOWERCASE_LETTER && currentType == Character.UPPERCASE_LETTER) {
+ int newTokenStart = pos - 1;
+ if (newTokenStart != tokenStart) {
+ list.add(new String(c, tokenStart, newTokenStart - tokenStart));
+ tokenStart = newTokenStart;
+ }
+ } else {
+ list.add(new String(c, tokenStart, pos - tokenStart));
+ tokenStart = pos;
+ }
+ currentType = type;
+ }
+ list.add(new String(c, tokenStart, c.length - tokenStart));
+ return (String[]) list.toArray(new String[list.size()]);
+ }
+
// Joining
//-----------------------------------------------------------------------
/**
- *
Concatenates elements of an array into a single String.
- * Null objects or empty strings within the array are represented by
+ *
Joins the provided elements into a single String.
+ *
+ * No separator is added to the joined String.
+ * Null objects or empty string elements are represented by
* empty strings.
*
*
@@ -2146,7 +3110,7 @@
* StringUtils.concatenate(["a", "b", "c"]) = "abc"
* StringUtils.concatenate([null, "", "a"]) = "a"
*
- *
+ *
* @param array the array of values to concatenate, may be null
* @return the concatenated String, null
if null array input
* @deprecated Use the better named {@link #join(Object[])} instead.
@@ -2155,37 +3119,37 @@
public static String concatenate(Object[] array) {
return join(array, null);
}
-
+
/**
* Joins the elements of the provided array into a single String
* containing the provided list of elements.
*
* No separator is added to the joined String.
- * Null objects or empty strings within the array are represented by
+ * Null objects or empty strings within the array are represented by
* empty strings.
- *
+ *
*
* StringUtils.join(null) = null
* StringUtils.join([]) = ""
* StringUtils.join([null]) = ""
* StringUtils.join(["a", "b", "c"]) = "abc"
* StringUtils.join([null, "", "a"]) = "a"
*
- *
+ *
* @param array the array of values to join together, may be null
* @return the joined String, null
if null array input
* @since 2.0
*/
public static String join(Object[] array) {
return join(array, null);
}
-
+
/**
* Joins the elements of the provided array into a single String
* containing the provided list of elements.
*
* No delimiter is added before or after the list.
- * Null objects or empty strings within the array are represented by
+ * Null objects or empty strings within the array are represented by
* empty strings.
*
*
@@ -2206,12 +3170,50 @@
if (array == null) {
return null;
}
- int arraySize = array.length;
- int bufSize = (arraySize == 0 ? 0 : ((array[0] == null ? 16 : array[0].toString().length()) + 1) * arraySize);
- StringBuffer buf = new StringBuffer(bufSize);
- for (int i = 0; i < arraySize; i++) {
- if (i > 0) {
+ return join(array, separator, 0, array.length);
+ }
+
+ /**
+ * Joins the elements of the provided array into a single String
+ * containing the provided list of elements.
+ *
+ * No delimiter is added before or after the list.
+ * Null objects or empty strings within the array are represented by
+ * empty strings.
+ *
+ *
+ * StringUtils.join(null, *) = null
+ * StringUtils.join([], *) = ""
+ * StringUtils.join([null], *) = ""
+ * StringUtils.join(["a", "b", "c"], ';') = "a;b;c"
+ * StringUtils.join(["a", "b", "c"], null) = "abc"
+ * StringUtils.join([null, "", "a"], ';') = ";;a"
+ *
+ *
+ * @param array the array of values to join together, may be null
+ * @param separator the separator character to use
+ * @param startIndex the first index to start joining from. It is
+ * an error to pass in an end index past the end of the array
+ * @param endIndex the index to stop joining from (exclusive). It is
+ * an error to pass in an end index past the end of the array
+ * @return the joined String, null
if null array input
+ * @since 2.0
+ */
+ public static String join(Object[] array, char separator, int startIndex, int endIndex) {
+ if (array == null) {
+ return null;
+ }
+ int bufSize = (endIndex - startIndex);
+ if (bufSize <= 0) {
+ return EMPTY;
+ }
+
+ bufSize *= ((array[startIndex] == null ? 16 : array[startIndex].toString().length()) + 1);
+ StrBuilder buf = new StrBuilder(bufSize);
+
+ for (int i = startIndex; i < endIndex; i++) {
+ if (i > startIndex) {
buf.append(separator);
}
if (array[i] != null) {
@@ -2221,13 +3223,14 @@
return buf.toString();
}
+
/**
* Joins the elements of the provided array into a single String
* containing the provided list of elements.
*
* No delimiter is added before or after the list.
- * A null
separator is the same as an empty String ("").
- * Null objects or empty strings within the array are represented by
+ * A null
separator is the same as an empty String ("").
+ * Null objects or empty strings within the array are represented by
* empty strings.
*
*
@@ -2248,23 +3251,58 @@
if (array == null) {
return null;
}
+ return join(array, separator, 0, array.length);
+ }
+
+ /**
+ * Joins the elements of the provided array into a single String
+ * containing the provided list of elements.
+ *
+ * No delimiter is added before or after the list.
+ * A null
separator is the same as an empty String ("").
+ * Null objects or empty strings within the array are represented by
+ * empty strings.
+ *
+ *
+ * StringUtils.join(null, *) = null
+ * StringUtils.join([], *) = ""
+ * StringUtils.join([null], *) = ""
+ * StringUtils.join(["a", "b", "c"], "--") = "a--b--c"
+ * StringUtils.join(["a", "b", "c"], null) = "abc"
+ * StringUtils.join(["a", "b", "c"], "") = "abc"
+ * StringUtils.join([null, "", "a"], ',') = ",,a"
+ *
+ *
+ * @param array the array of values to join together, may be null
+ * @param separator the separator character to use, null treated as ""
+ * @param startIndex the first index to start joining from. It is
+ * an error to pass in an end index past the end of the array
+ * @param endIndex the index to stop joining from (exclusive). It is
+ * an error to pass in an end index past the end of the array
+ * @return the joined String, null
if null array input
+ */
+ public static String join(Object[] array, String separator, int startIndex, int endIndex) {
+ if (array == null) {
+ return null;
+ }
if (separator == null) {
separator = EMPTY;
}
- int arraySize = array.length;
- // ArraySize == 0: Len = 0
- // ArraySize > 0: Len = NofStrings *(len(firstString) + len(separator))
+ // endIndex - startIndex > 0: Len = NofStrings *(len(firstString) + len(separator))
// (Assuming that all Strings are roughly equally long)
- int bufSize
- = ((arraySize == 0) ? 0
- : arraySize * ((array[0] == null ? 16 : array[0].toString().length())
- + ((separator != null) ? separator.length(): 0)));
+ int bufSize = (endIndex - startIndex);
+ if (bufSize <= 0) {
+ return EMPTY;
+ }
- StringBuffer buf = new StringBuffer(bufSize);
+ bufSize *= ((array[startIndex] == null ? 16 : array[startIndex].toString().length())
+ + separator.length());
- for (int i = 0; i < arraySize; i++) {
- if ((separator != null) && (i > 0)) {
+ StrBuilder buf = new StrBuilder(bufSize);
+
+ for (int i = startIndex; i < endIndex; i++) {
+ if (i > startIndex) {
buf.append(separator);
}
if (array[i] != null) {
@@ -2278,7 +3316,7 @@
* Joins the elements of the provided Iterator
into
* a single String containing the provided elements.
*
- * No delimiter is added before or after the list. Null objects or empty
+ *
No delimiter is added before or after the list. Null objects or empty
* strings within the iteration are represented by empty strings.
*
* See the examples here: {@link #join(Object[],char)}.
@@ -2289,19 +3327,33 @@
* @since 2.0
*/
public static String join(Iterator iterator, char separator) {
+
+ // handle null, zero and one elements before building a buffer
if (iterator == null) {
return null;
}
- StringBuffer buf = new StringBuffer(256); // Java default is 16, probably too small
+ if (!iterator.hasNext()) {
+ return EMPTY;
+ }
+ Object first = iterator.next();
+ if (!iterator.hasNext()) {
+ return ObjectUtils.toString(first);
+ }
+
+ // two or more elements
+ StrBuilder buf = new StrBuilder(256); // Java default is 16, probably too small
+ if (first != null) {
+ buf.append(first);
+ }
+
while (iterator.hasNext()) {
+ buf.append(separator);
Object obj = iterator.next();
if (obj != null) {
buf.append(obj);
}
- if (iterator.hasNext()) {
- buf.append(separator);
- }
}
+
return buf.toString();
}
@@ -2319,29 +3371,86 @@
* @return the joined String, null
if null iterator input
*/
public static String join(Iterator iterator, String separator) {
+
+ // handle null, zero and one elements before building a buffer
if (iterator == null) {
return null;
}
- StringBuffer buf = new StringBuffer(256); // Java default is 16, probably too small
+ if (!iterator.hasNext()) {
+ return EMPTY;
+ }
+ Object first = iterator.next();
+ if (!iterator.hasNext()) {
+ return ObjectUtils.toString(first);
+ }
+
+ // two or more elements
+ StrBuilder buf = new StrBuilder(256); // Java default is 16, probably too small
+ if (first != null) {
+ buf.append(first);
+ }
+
while (iterator.hasNext()) {
+ if (separator != null) {
+ buf.append(separator);
+ }
Object obj = iterator.next();
if (obj != null) {
buf.append(obj);
}
- if ((separator != null) && iterator.hasNext()) {
- buf.append(separator);
- }
- }
+ }
return buf.toString();
}
+ /**
+ * Joins the elements of the provided Collection
into
+ * a single String containing the provided elements.
+ *
+ * No delimiter is added before or after the list. Null objects or empty
+ * strings within the iteration are represented by empty strings.
+ *
+ * See the examples here: {@link #join(Object[],char)}.
+ *
+ * @param collection the Collection
of values to join together, may be null
+ * @param separator the separator character to use
+ * @return the joined String, null
if null iterator input
+ * @since 2.3
+ */
+ public static String join(Collection collection, char separator) {
+ if (collection == null) {
+ return null;
+ }
+ return join(collection.iterator(), separator);
+ }
+
+ /**
+ * Joins the elements of the provided Collection
into
+ * a single String containing the provided elements.
+ *
+ * No delimiter is added before or after the list.
+ * A null
separator is the same as an empty String ("").
+ *
+ * See the examples here: {@link #join(Object[],String)}.
+ *
+ * @param collection the Collection
of values to join together, may be null
+ * @param separator the separator character to use, null treated as ""
+ * @return the joined String, null
if null iterator input
+ * @since 2.3
+ */
+ public static String join(Collection collection, String separator) {
+ if (collection == null) {
+ return null;
+ }
+ return join(collection.iterator(), separator);
+ }
+
// Delete
//-----------------------------------------------------------------------
/**
* Deletes all 'space' characters from a String as defined by
* {@link Character#isSpace(char)}.
- *
- * This is the only StringUtils method that uses the
+ *
+ *
This is the only StringUtils method that uses the
* isSpace
definition. You are advised to use
* {@link #deleteWhitespace(String)} instead as whitespace is much
* better localized.
@@ -2354,7 +3463,7 @@
* StringUtils.deleteSpaces("ab c") = "abc"
* StringUtils.deleteSpaces("a\nb\tc ") = "abc"
*
- *
+ *
* Spaces are defined as {' ', '\t', '\r', '\n', '\b'}
* in line with the deprecated isSpace
method.
*
@@ -2380,76 +3489,286 @@
* StringUtils.deleteWhitespace("abc") = "abc"
* StringUtils.deleteWhitespace(" ab c ") = "abc"
*
- *
+ *
* @param str the String to delete whitespace from, may be null
* @return the String without whitespaces, null
if null String input
*/
public static String deleteWhitespace(String str) {
- if (str == null) {
- return null;
+ if (isEmpty(str)) {
+ return str;
}
int sz = str.length();
- StringBuffer buffer = new StringBuffer(sz);
+ char[] chs = new char[sz];
+ int count = 0;
for (int i = 0; i < sz; i++) {
if (!Character.isWhitespace(str.charAt(i))) {
- buffer.append(str.charAt(i));
+ chs[count++] = str.charAt(i);
}
}
- return buffer.toString();
+ if (count == sz) {
+ return str;
+ }
+ return new String(chs, 0, count);
}
+ // Remove
+ //-----------------------------------------------------------------------
+ /**
+ * Removes a substring only if it is at the begining of a source string,
+ * otherwise returns the source string.
+ *
+ * A null
source string will return null
.
+ * An empty ("") source string will return the empty string.
+ * A null
search string will return the source string.
+ *
+ *
+ * StringUtils.removeStart(null, *) = null
+ * StringUtils.removeStart("", *) = ""
+ * StringUtils.removeStart(*, null) = *
+ * StringUtils.removeStart("www.domain.com", "www.") = "domain.com"
+ * StringUtils.removeStart("domain.com", "www.") = "domain.com"
+ * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com"
+ * StringUtils.removeStart("abc", "") = "abc"
+ *
+ *
+ * @param str the source String to search, may be null
+ * @param remove the String to search for and remove, may be null
+ * @return the substring with the string removed if found,
+ * null
if null String input
+ * @since 2.1
+ */
+ public static String removeStart(String str, String remove) {
+ if (isEmpty(str) || isEmpty(remove)) {
+ return str;
+ }
+ if (str.startsWith(remove)){
+ return str.substring(remove.length());
+ }
+ return str;
+ }
+
+ /**
+ * Case insensitive removal of a substring if it is at the begining of a source string,
+ * otherwise returns the source string.
+ *
+ * A null
source string will return null
.
+ * An empty ("") source string will return the empty string.
+ * A null
search string will return the source string.
+ *
+ *
+ * StringUtils.removeStartIgnoreCase(null, *) = null
+ * StringUtils.removeStartIgnoreCase("", *) = ""
+ * StringUtils.removeStartIgnoreCase(*, null) = *
+ * StringUtils.removeStartIgnoreCase("www.domain.com", "www.") = "domain.com"
+ * StringUtils.removeStartIgnoreCase("www.domain.com", "WWW.") = "domain.com"
+ * StringUtils.removeStartIgnoreCase("domain.com", "www.") = "domain.com"
+ * StringUtils.removeStartIgnoreCase("www.domain.com", "domain") = "www.domain.com"
+ * StringUtils.removeStartIgnoreCase("abc", "") = "abc"
+ *
+ *
+ * @param str the source String to search, may be null
+ * @param remove the String to search for (case insensitive) and remove, may be null
+ * @return the substring with the string removed if found,
+ * null
if null String input
+ * @since 2.4
+ */
+ public static String removeStartIgnoreCase(String str, String remove) {
+ if (isEmpty(str) || isEmpty(remove)) {
+ return str;
+ }
+ if (startsWithIgnoreCase(str, remove)) {
+ return str.substring(remove.length());
+ }
+ return str;
+ }
+
+ /**
+ * Removes a substring only if it is at the end of a source string,
+ * otherwise returns the source string.
+ *
+ * A null
source string will return null
.
+ * An empty ("") source string will return the empty string.
+ * A null
search string will return the source string.
+ *
+ *
+ * StringUtils.removeEnd(null, *) = null
+ * StringUtils.removeEnd("", *) = ""
+ * StringUtils.removeEnd(*, null) = *
+ * StringUtils.removeEnd("www.domain.com", ".com.") = "www.domain.com"
+ * StringUtils.removeEnd("www.domain.com", ".com") = "www.domain"
+ * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com"
+ * StringUtils.removeEnd("abc", "") = "abc"
+ *
+ *
+ * @param str the source String to search, may be null
+ * @param remove the String to search for and remove, may be null
+ * @return the substring with the string removed if found,
+ * null
if null String input
+ * @since 2.1
+ */
+ public static String removeEnd(String str, String remove) {
+ if (isEmpty(str) || isEmpty(remove)) {
+ return str;
+ }
+ if (str.endsWith(remove)) {
+ return str.substring(0, str.length() - remove.length());
+ }
+ return str;
+ }
+
+ /**
+ * Case insensitive removal of a substring if it is at the end of a source string,
+ * otherwise returns the source string.
+ *
+ * A null
source string will return null
.
+ * An empty ("") source string will return the empty string.
+ * A null
search string will return the source string.
+ *
+ *
+ * StringUtils.removeEndIgnoreCase(null, *) = null
+ * StringUtils.removeEndIgnoreCase("", *) = ""
+ * StringUtils.removeEndIgnoreCase(*, null) = *
+ * StringUtils.removeEndIgnoreCase("www.domain.com", ".com.") = "www.domain.com"
+ * StringUtils.removeEndIgnoreCase("www.domain.com", ".com") = "www.domain"
+ * StringUtils.removeEndIgnoreCase("www.domain.com", "domain") = "www.domain.com"
+ * StringUtils.removeEndIgnoreCase("abc", "") = "abc"
+ * StringUtils.removeEndIgnoreCase("www.domain.com", ".COM") = "www.domain")
+ * StringUtils.removeEndIgnoreCase("www.domain.COM", ".com") = "www.domain")
+ *
+ *
+ * @param str the source String to search, may be null
+ * @param remove the String to search for (case insensitive) and remove, may be null
+ * @return the substring with the string removed if found,
+ * null
if null String input
+ * @since 2.4
+ */
+ public static String removeEndIgnoreCase(String str, String remove) {
+ if (isEmpty(str) || isEmpty(remove)) {
+ return str;
+ }
+ if (endsWithIgnoreCase(str, remove)) {
+ return str.substring(0, str.length() - remove.length());
+ }
+ return str;
+ }
+
+ /**
+ * Removes all occurrences of a substring from within the source string.
+ *
+ * A null
source string will return null
.
+ * An empty ("") source string will return the empty string.
+ * A null
remove string will return the source string.
+ * An empty ("") remove string will return the source string.
+ *
+ *
+ * StringUtils.remove(null, *) = null
+ * StringUtils.remove("", *) = ""
+ * StringUtils.remove(*, null) = *
+ * StringUtils.remove(*, "") = *
+ * StringUtils.remove("queued", "ue") = "qd"
+ * StringUtils.remove("queued", "zz") = "queued"
+ *
+ *
+ * @param str the source String to search, may be null
+ * @param remove the String to search for and remove, may be null
+ * @return the substring with the string removed if found,
+ * null
if null String input
+ * @since 2.1
+ */
+ public static String remove(String str, String remove) {
+ if (isEmpty(str) || isEmpty(remove)) {
+ return str;
+ }
+ return replace(str, remove, EMPTY, -1);
+ }
+
+ /**
+ * Removes all occurrences of a character from within the source string.
+ *
+ * A null
source string will return null
.
+ * An empty ("") source string will return the empty string.
+ *
+ *
+ * StringUtils.remove(null, *) = null
+ * StringUtils.remove("", *) = ""
+ * StringUtils.remove("queued", 'u') = "qeed"
+ * StringUtils.remove("queued", 'z') = "queued"
+ *
+ *
+ * @param str the source String to search, may be null
+ * @param remove the char to search for and remove, may be null
+ * @return the substring with the char removed if found,
+ * null
if null String input
+ * @since 2.1
+ */
+ public static String remove(String str, char remove) {
+ if (isEmpty(str) || str.indexOf(remove) == INDEX_NOT_FOUND) {
+ return str;
+ }
+ char[] chars = str.toCharArray();
+ int pos = 0;
+ for (int i = 0; i < chars.length; i++) {
+ if (chars[i] != remove) {
+ chars[pos++] = chars[i];
+ }
+ }
+ return new String(chars, 0, pos);
+ }
+
// Replacing
//-----------------------------------------------------------------------
/**
* Replaces a String with another String inside a larger String, once.
- *
+ *
* A null
reference passed to this method is a no-op.
- *
+ *
*
* StringUtils.replaceOnce(null, *, *) = null
* StringUtils.replaceOnce("", *, *) = ""
- * StringUtils.replaceOnce("aba", null, null) = "aba"
- * StringUtils.replaceOnce("aba", null, null) = "aba"
+ * StringUtils.replaceOnce("any", null, *) = "any"
+ * StringUtils.replaceOnce("any", *, null) = "any"
+ * StringUtils.replaceOnce("any", "", *) = "any"
* StringUtils.replaceOnce("aba", "a", null) = "aba"
- * StringUtils.replaceOnce("aba", "a", "") = "aba"
+ * StringUtils.replaceOnce("aba", "a", "") = "ba"
* StringUtils.replaceOnce("aba", "a", "z") = "zba"
*
- *
- * @see #replace(String text, String repl, String with, int max)
+ *
+ * @see #replace(String text, String searchString, String replacement, int max)
* @param text text to search and replace in, may be null
- * @param repl the String to search for, may be null
- * @param with the String to replace with, may be null
+ * @param searchString the String to search for, may be null
+ * @param replacement the String to replace with, may be null
* @return the text with any replacements processed,
* null
if null String input
*/
- public static String replaceOnce(String text, String repl, String with) {
- return replace(text, repl, with, 1);
+ public static String replaceOnce(String text, String searchString, String replacement) {
+ return replace(text, searchString, replacement, 1);
}
/**
- * Replaces all occurances of a String within another String.
+ * Replaces all occurrences of a String within another String.
*
* A null
reference passed to this method is a no-op.
- *
+ *
*
* StringUtils.replace(null, *, *) = null
* StringUtils.replace("", *, *) = ""
- * StringUtils.replace("aba", null, null) = "aba"
- * StringUtils.replace("aba", null, null) = "aba"
+ * StringUtils.replace("any", null, *) = "any"
+ * StringUtils.replace("any", *, null) = "any"
+ * StringUtils.replace("any", "", *) = "any"
* StringUtils.replace("aba", "a", null) = "aba"
- * StringUtils.replace("aba", "a", "") = "aba"
+ * StringUtils.replace("aba", "a", "") = "b"
* StringUtils.replace("aba", "a", "z") = "zbz"
*
- *
- * @see #replace(String text, String repl, String with, int max)
+ *
+ * @see #replace(String text, String searchString, String replacement, int max)
* @param text text to search and replace in, may be null
- * @param repl the String to search for, may be null
- * @param with the String to replace with, may be null
+ * @param searchString the String to search for, may be null
+ * @param replacement the String to replace it with, may be null
* @return the text with any replacements processed,
* null
if null String input
*/
- public static String replace(String text, String repl, String with) {
- return replace(text, repl, with, -1);
+ public static String replace(String text, String searchString, String replacement) {
+ return replace(text, searchString, replacement, -1);
}
/**
@@ -2461,58 +3780,341 @@
*
* StringUtils.replace(null, *, *, *) = null
* StringUtils.replace("", *, *, *) = ""
- * StringUtils.replace("abaa", null, null, 1) = "abaa"
- * StringUtils.replace("abaa", null, null, 1) = "abaa"
- * StringUtils.replace("abaa", "a", null, 1) = "abaa"
- * StringUtils.replace("abaa", "a", "", 1) = "abaa"
+ * StringUtils.replace("any", null, *, *) = "any"
+ * StringUtils.replace("any", *, null, *) = "any"
+ * StringUtils.replace("any", "", *, *) = "any"
+ * StringUtils.replace("any", *, *, 0) = "any"
+ * StringUtils.replace("abaa", "a", null, -1) = "abaa"
+ * StringUtils.replace("abaa", "a", "", -1) = "b"
* StringUtils.replace("abaa", "a", "z", 0) = "abaa"
* StringUtils.replace("abaa", "a", "z", 1) = "zbaa"
* StringUtils.replace("abaa", "a", "z", 2) = "zbza"
* StringUtils.replace("abaa", "a", "z", -1) = "zbzz"
*
- *
+ *
* @param text text to search and replace in, may be null
- * @param repl the String to search for, may be null
- * @param with the String to replace with, may be null
+ * @param searchString the String to search for, may be null
+ * @param replacement the String to replace it with, may be null
* @param max maximum number of values to replace, or -1
if no maximum
* @return the text with any replacements processed,
* null
if null String input
*/
- public static String replace(String text, String repl, String with, int max) {
- if (text == null || repl == null || with == null || repl.length() == 0 || max == 0) {
+ public static String replace(String text, String searchString, String replacement, int max) {
+ if (isEmpty(text) || isEmpty(searchString) || replacement == null || max == 0) {
return text;
}
-
- StringBuffer buf = new StringBuffer(text.length());
- int start = 0, end = 0;
- while ((end = text.indexOf(repl, start)) != -1) {
- buf.append(text.substring(start, end)).append(with);
- start = end + repl.length();
-
+ int start = 0;
+ int end = text.indexOf(searchString, start);
+ if (end == INDEX_NOT_FOUND) {
+ return text;
+ }
+ int replLength = searchString.length();
+ int increase = replacement.length() - replLength;
+ increase = (increase < 0 ? 0 : increase);
+ increase *= (max < 0 ? 16 : (max > 64 ? 64 : max));
+ StrBuilder buf = new StrBuilder(text.length() + increase);
+ while (end != INDEX_NOT_FOUND) {
+ buf.append(text.substring(start, end)).append(replacement);
+ start = end + replLength;
if (--max == 0) {
break;
}
+ end = text.indexOf(searchString, start);
}
buf.append(text.substring(start));
return buf.toString();
}
-
+
+ /**
+ *
+ * Replaces all occurrences of Strings within another String.
+ *
+ *
+ *
+ * A null
reference passed to this method is a no-op, or if
+ * any "search string" or "string to replace" is null, that replace will be
+ * ignored. This will not repeat. For repeating replaces, call the
+ * overloaded method.
+ *
+ *
+ *
+ * StringUtils.replaceEach(null, *, *) = null
+ * StringUtils.replaceEach("", *, *) = ""
+ * StringUtils.replaceEach("aba", null, null) = "aba"
+ * StringUtils.replaceEach("aba", new String[0], null) = "aba"
+ * StringUtils.replaceEach("aba", null, new String[0]) = "aba"
+ * StringUtils.replaceEach("aba", new String[]{"a"}, null) = "aba"
+ * StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}) = "b"
+ * StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}) = "aba"
+ * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte"
+ * (example of how it does not repeat)
+ * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "dcte"
+ *
+ *
+ * @param text
+ * text to search and replace in, no-op if null
+ * @param searchList
+ * the Strings to search for, no-op if null
+ * @param replacementList
+ * the Strings to replace them with, no-op if null
+ * @return the text with any replacements processed, null
if
+ * null String input
+ * @throws IndexOutOfBoundsException
+ * if the lengths of the arrays are not the same (null is ok,
+ * and/or size 0)
+ * @since 2.4
+ */
+ public static String replaceEach(String text, String[] searchList, String[] replacementList) {
+ return replaceEach(text, searchList, replacementList, false, 0);
+ }
+
+ /**
+ *
+ * Replaces all occurrences of Strings within another String.
+ *
+ *
+ *
+ * A null
reference passed to this method is a no-op, or if
+ * any "search string" or "string to replace" is null, that replace will be
+ * ignored. This will not repeat. For repeating replaces, call the
+ * overloaded method.
+ *
+ *
+ *
+ * StringUtils.replaceEach(null, *, *, *) = null
+ * StringUtils.replaceEach("", *, *, *) = ""
+ * StringUtils.replaceEach("aba", null, null, *) = "aba"
+ * StringUtils.replaceEach("aba", new String[0], null, *) = "aba"
+ * StringUtils.replaceEach("aba", null, new String[0], *) = "aba"
+ * StringUtils.replaceEach("aba", new String[]{"a"}, null, *) = "aba"
+ * StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}, *) = "b"
+ * StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}, *) = "aba"
+ * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}, *) = "wcte"
+ * (example of how it repeats)
+ * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, false) = "dcte"
+ * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, true) = "tcte"
+ * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, true) = IllegalArgumentException
+ * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, false) = "dcabe"
+ *
+ *
+ * @param text
+ * text to search and replace in, no-op if null
+ * @param searchList
+ * the Strings to search for, no-op if null
+ * @param replacementList
+ * the Strings to replace them with, no-op if null
+ * @return the text with any replacements processed, null
if
+ * null String input
+ * @throws IllegalArgumentException
+ * if the search is repeating and there is an endless loop due
+ * to outputs of one being inputs to another
+ * @throws IndexOutOfBoundsException
+ * if the lengths of the arrays are not the same (null is ok,
+ * and/or size 0)
+ * @since 2.4
+ */
+ public static String replaceEachRepeatedly(String text, String[] searchList, String[] replacementList) {
+ // timeToLive should be 0 if not used or nothing to replace, else it's
+ // the length of the replace array
+ int timeToLive = searchList == null ? 0 : searchList.length;
+ return replaceEach(text, searchList, replacementList, true, timeToLive);
+ }
+
+ /**
+ *
+ * Replaces all occurrences of Strings within another String.
+ *
+ *
+ *
+ * A null
reference passed to this method is a no-op, or if
+ * any "search string" or "string to replace" is null, that replace will be
+ * ignored.
+ *
+ *
+ *
+ * StringUtils.replaceEach(null, *, *, *) = null
+ * StringUtils.replaceEach("", *, *, *) = ""
+ * StringUtils.replaceEach("aba", null, null, *) = "aba"
+ * StringUtils.replaceEach("aba", new String[0], null, *) = "aba"
+ * StringUtils.replaceEach("aba", null, new String[0], *) = "aba"
+ * StringUtils.replaceEach("aba", new String[]{"a"}, null, *) = "aba"
+ * StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}, *) = "b"
+ * StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}, *) = "aba"
+ * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}, *) = "wcte"
+ * (example of how it repeats)
+ * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, false) = "dcte"
+ * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, true) = "tcte"
+ * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, *) = IllegalArgumentException
+ *
+ *
+ * @param text
+ * text to search and replace in, no-op if null
+ * @param searchList
+ * the Strings to search for, no-op if null
+ * @param replacementList
+ * the Strings to replace them with, no-op if null
+ * @param repeat if true, then replace repeatedly
+ * until there are no more possible replacements or timeToLive < 0
+ * @param timeToLive
+ * if less than 0 then there is a circular reference and endless
+ * loop
+ * @return the text with any replacements processed, null
if
+ * null String input
+ * @throws IllegalArgumentException
+ * if the search is repeating and there is an endless loop due
+ * to outputs of one being inputs to another
+ * @throws IndexOutOfBoundsException
+ * if the lengths of the arrays are not the same (null is ok,
+ * and/or size 0)
+ * @since 2.4
+ */
+ private static String replaceEach(String text, String[] searchList, String[] replacementList,
+ boolean repeat, int timeToLive)
+ {
+
+ // mchyzer Performance note: This creates very few new objects (one major goal)
+ // let me know if there are performance requests, we can create a harness to measure
+
+ if (text == null || text.length() == 0 || searchList == null ||
+ searchList.length == 0 || replacementList == null || replacementList.length == 0)
+ {
+ return text;
+ }
+
+ // if recursing, this shouldnt be less than 0
+ if (timeToLive < 0) {
+ throw new IllegalStateException("TimeToLive of " + timeToLive + " is less than 0: " + text);
+ }
+
+ int searchLength = searchList.length;
+ int replacementLength = replacementList.length;
+
+ // make sure lengths are ok, these need to be equal
+ if (searchLength != replacementLength) {
+ throw new IllegalArgumentException("Search and Replace array lengths don't match: "
+ + searchLength
+ + " vs "
+ + replacementLength);
+ }
+
+ // keep track of which still have matches
+ boolean[] noMoreMatchesForReplIndex = new boolean[searchLength];
+
+ // index on index that the match was found
+ int textIndex = -1;
+ int replaceIndex = -1;
+ int tempIndex = -1;
+
+ // index of replace array that will replace the search string found
+ // NOTE: logic duplicated below START
+ for (int i = 0; i < searchLength; i++) {
+ if (noMoreMatchesForReplIndex[i] || searchList[i] == null ||
+ searchList[i].length() == 0 || replacementList[i] == null)
+ {
+ continue;
+ }
+ tempIndex = text.indexOf(searchList[i]);
+
+ // see if we need to keep searching for this
+ if (tempIndex == -1) {
+ noMoreMatchesForReplIndex[i] = true;
+ } else {
+ if (textIndex == -1 || tempIndex < textIndex) {
+ textIndex = tempIndex;
+ replaceIndex = i;
+ }
+ }
+ }
+ // NOTE: logic mostly below END
+
+ // no search strings found, we are done
+ if (textIndex == -1) {
+ return text;
+ }
+
+ int start = 0;
+
+ // get a good guess on the size of the result buffer so it doesnt have to double if it goes over a bit
+ int increase = 0;
+
+ // count the replacement text elements that are larger than their corresponding text being replaced
+ for (int i = 0; i < searchList.length; i++) {
+ if (searchList[i] == null || replacementList[i] == null) {
+ continue;
+ }
+ int greater = replacementList[i].length() - searchList[i].length();
+ if (greater > 0) {
+ increase += 3 * greater; // assume 3 matches
+ }
+ }
+ // have upper-bound at 20% increase, then let Java take over
+ increase = Math.min(increase, text.length() / 5);
+
+ StrBuilder buf = new StrBuilder(text.length() + increase);
+
+ while (textIndex != -1) {
+
+ for (int i = start; i < textIndex; i++) {
+ buf.append(text.charAt(i));
+ }
+ buf.append(replacementList[replaceIndex]);
+
+ start = textIndex + searchList[replaceIndex].length();
+
+ textIndex = -1;
+ replaceIndex = -1;
+ tempIndex = -1;
+ // find the next earliest match
+ // NOTE: logic mostly duplicated above START
+ for (int i = 0; i < searchLength; i++) {
+ if (noMoreMatchesForReplIndex[i] || searchList[i] == null ||
+ searchList[i].length() == 0 || replacementList[i] == null)
+ {
+ continue;
+ }
+ tempIndex = text.indexOf(searchList[i], start);
+
+ // see if we need to keep searching for this
+ if (tempIndex == -1) {
+ noMoreMatchesForReplIndex[i] = true;
+ } else {
+ if (textIndex == -1 || tempIndex < textIndex) {
+ textIndex = tempIndex;
+ replaceIndex = i;
+ }
+ }
+ }
+ // NOTE: logic duplicated above END
+
+ }
+ int textLength = text.length();
+ for (int i = start; i < textLength; i++) {
+ buf.append(text.charAt(i));
+ }
+ String result = buf.toString();
+ if (!repeat) {
+ return result;
+ }
+
+ return replaceEach(result, searchList, replacementList, repeat, timeToLive - 1);
+ }
+
// Replace, character based
//-----------------------------------------------------------------------
/**
- * Replaces all occurrances of a character in a String with another.
+ *
Replaces all occurrences of a character in a String with another.
* This is a null-safe version of {@link String#replace(char, char)}.
*
* A null
string input returns null
.
* An empty ("") string input returns an empty string.
- *
+ *
*
* StringUtils.replaceChars(null, *, *) = null
* StringUtils.replaceChars("", *, *) = ""
* StringUtils.replaceChars("abcba", 'b', 'y') = "aycya"
* StringUtils.replaceChars("abcba", 'z', 'y') = "abcba"
*
- *
+ *
* @param str String to replace characters in, may be null
* @param searchChar the character to search for, may be null
* @param replaceChar the character to replace, may be null
@@ -2525,25 +4127,25 @@
}
return str.replace(searchChar, replaceChar);
}
-
+
/**
* Replaces multiple characters in a String in one go.
* This method can also be used to delete characters.
*
* For example:
* replaceChars("hello", "ho", "jy") = jelly
.
- *
+ *
* A null
string input returns null
.
* An empty ("") string input returns an empty string.
* A null or empty set of search characters returns the input string.
- *
+ *
* The length of the search characters should normally equal the length
* of the replace characters.
* If the search characters is longer, then the extra search characters
* are deleted.
* If the search characters is shorter, then the extra replace characters
* are ignored.
- *
+ *
*
* StringUtils.replaceChars(null, *, *) = null
* StringUtils.replaceChars("", *, *) = ""
@@ -2555,47 +4157,40 @@
* StringUtils.replaceChars("abcba", "bc", "y") = "ayya"
* StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya"
*
- *
+ *
* @param str String to replace characters in, may be null
* @param searchChars a set of characters to search for, may be null
* @param replaceChars a set of characters to replace, may be null
* @return modified String, null
if null string input
* @since 2.0
*/
public static String replaceChars(String str, String searchChars, String replaceChars) {
- if (str == null || str.length() == 0 || searchChars == null || searchChars.length()== 0) {
+ if (isEmpty(str) || isEmpty(searchChars)) {
return str;
}
- char[] chars = str.toCharArray();
- int len = chars.length;
+ if (replaceChars == null) {
+ replaceChars = EMPTY;
+ }
boolean modified = false;
- for (int i = 0, isize = searchChars.length(); i < isize; i++) {
- char searchChar = searchChars.charAt(i);
- if (replaceChars == null || i >= replaceChars.length()) {
- // delete
- int pos = 0;
- for (int j = 0; j < len; j++) {
- if (chars[j] != searchChar) {
- chars[pos++] = chars[j];
- } else {
- modified = true;
- }
+ int replaceCharsLength = replaceChars.length();
+ int strLength = str.length();
+ StrBuilder buf = new StrBuilder(strLength);
+ for (int i = 0; i < strLength; i++) {
+ char ch = str.charAt(i);
+ int index = searchChars.indexOf(ch);
+ if (index >= 0) {
+ modified = true;
+ if (index < replaceCharsLength) {
+ buf.append(replaceChars.charAt(index));
}
- len = pos;
} else {
- // replace
- for (int j = 0; j < len; j++) {
- if (chars[j] == searchChar) {
- chars[j] = replaceChars.charAt(i);
- modified = true;
- }
- }
+ buf.append(ch);
}
}
- if (modified == false) {
- return str;
+ if (modified) {
+ return buf.toString();
}
- return new String(chars, 0, len);
+ return str;
}
// Overlay
@@ -2614,7 +4209,7 @@
* StringUtils.overlayString("abcdef", "zzzz", -1, 4) = IndexOutOfBoundsException
* StringUtils.overlayString("abcdef", "zzzz", 2, 8) = IndexOutOfBoundsException
*
- *
+ *
* @param text the String to do overlaying in, may be null
* @param overlay the String to overlay, may be null
* @param start the position to start overlaying at, must be valid
@@ -2626,7 +4221,7 @@
* Method will be removed in Commons Lang 3.0.
*/
public static String overlayString(String text, String overlay, int start, int end) {
- return new StringBuffer(start + overlay.length() + text.length() - end + 1)
+ return new StrBuilder(start + overlay.length() + text.length() - end + 1)
.append(text.substring(0, start))
.append(overlay)
.append(text.substring(end))
@@ -2635,7 +4230,7 @@
/**
* Overlays part of a String with another String.
- *
+ *
* A null
string input returns null
.
* A negative index is treated as zero.
* An index greater than the string length is treated as the string length.
@@ -2654,7 +4249,7 @@
* StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef"
* StringUtils.overlay("abcdef", "zzzz", 8, 10) = "abcdefzzzz"
*
- *
+ *
* @param str the String to do overlaying in, may be null
* @param overlay the String to overlay, may be null
* @param start the position to start overlaying at
@@ -2687,7 +4282,7 @@
start = end;
end = temp;
}
- return new StringBuffer(len + start - end + overlay.length() + 1)
+ return new StrBuilder(len + start - end + overlay.length() + 1)
.append(str.substring(0, start))
.append(overlay)
.append(str.substring(end))
@@ -2722,29 +4317,26 @@
* @return String without newline, null
if null String input
*/
public static String chomp(String str) {
- if (str == null || str.length() == 0) {
+ if (isEmpty(str)) {
return str;
}
if (str.length() == 1) {
char ch = str.charAt(0);
- if (ch == '\r' || ch == '\n') {
+ if (ch == CharUtils.CR || ch == CharUtils.LF) {
return EMPTY;
- } else {
- return str;
}
+ return str;
}
int lastIdx = str.length() - 1;
char last = str.charAt(lastIdx);
- if (last == '\n') {
- if (str.charAt(lastIdx - 1) == '\r') {
+ if (last == CharUtils.LF) {
+ if (str.charAt(lastIdx - 1) == CharUtils.CR) {
lastIdx--;
}
- } else if (last == '\r') {
-
- } else {
+ } else if (last != CharUtils.CR) {
lastIdx++;
}
return str.substring(0, lastIdx);
@@ -2765,7 +4357,7 @@
* StringUtils.chomp("foobar", "bar") = "foo"
* StringUtils.chomp("foobar", "baz") = "foobar"
* StringUtils.chomp("foo", "foo") = ""
- * StringUtils.chomp("foo ", "foo") = "foo"
+ * StringUtils.chomp("foo ", "foo") = "foo "
* StringUtils.chomp(" foo", "foo") = " "
* StringUtils.chomp("foo", "foooo") = "foo"
* StringUtils.chomp("foo", "") = "foo"
@@ -2777,7 +4369,7 @@
* @return String without trailing separator, null
if null String input
*/
public static String chomp(String str, String separator) {
- if (str == null || str.length() == 0 || separator == null) {
+ if (isEmpty(str) || separator == null) {
return str;
}
if (str.endsWith(separator)) {
@@ -2789,7 +4381,7 @@
/**
* Remove any "\n" if and only if it is at the end
* of the supplied String.
- *
+ *
* @param str the String to chomp from, must not be null
* @return String without chomped ending
* @throws NullPointerException if str is null
@@ -2799,10 +4391,10 @@
public static String chompLast(String str) {
return chompLast(str, "\n");
}
-
+
/**
* Remove a value if and only if the String ends with that value.
- *
+ *
* @param str the String to chomp from, must not be null
* @param sep the String to chomp, must not be null
* @return String without chomped ending
@@ -2817,12 +4409,11 @@
String sub = str.substring(str.length() - sep.length());
if (sep.equals(sub)) {
return str.substring(0, str.length() - sep.length());
- } else {
- return str;
}
+ return str;
}
- /**
+ /**
* Remove everything and return the last value of a supplied String, and
* everything after it from a String.
*
@@ -2845,7 +4436,7 @@
}
}
- /**
+ /**
* Remove the first value of a supplied String, and everything before it
* from a String.
*
@@ -2858,14 +4449,13 @@
*/
public static String prechomp(String str, String sep) {
int idx = str.indexOf(sep);
- if (idx != -1) {
- return str.substring(idx + sep.length());
- } else {
+ if (idx == -1) {
return str;
- }
+ }
+ return str.substring(idx + sep.length());
}
- /**
+ /**
* Remove and return everything before the first value of a
* supplied String from another String.
*
@@ -2879,11 +4469,10 @@
*/
public static String getPrechomp(String str, String sep) {
int idx = str.indexOf(sep);
- if (idx != -1) {
- return str.substring(0, idx + sep.length());
- } else {
+ if (idx == -1) {
return EMPTY;
- }
+ }
+ return str.substring(0, idx + sep.length());
}
// Chopping
@@ -2922,8 +4511,8 @@
int lastIdx = strLen - 1;
String ret = str.substring(0, lastIdx);
char last = str.charAt(lastIdx);
- if (last == '\n') {
- if (ret.charAt(lastIdx - 1) == '\r') {
+ if (last == CharUtils.LF) {
+ if (ret.charAt(lastIdx - 1) == CharUtils.CR) {
return ret.substring(0, lastIdx - 1);
}
}
@@ -2946,8 +4535,8 @@
return EMPTY;
}
char last = str.charAt(lastIdx);
- if (last == '\n') {
- if (str.charAt(lastIdx - 1) == '\r') {
+ if (last == CharUtils.LF) {
+ if (str.charAt(lastIdx - 1) == CharUtils.CR) {
lastIdx--;
}
} else {
@@ -2956,7 +4545,6 @@
return str.substring(0, lastIdx);
}
-
// Conversion
//-----------------------------------------------------------------------
/**
@@ -3001,7 +4589,7 @@
*/
public static String repeat(String str, int repeat) {
// Performance tuned for 2.0 (JDK1.4)
-
+
if (str == null) {
return null;
}
@@ -3013,37 +4601,67 @@
return str;
}
if (inputLength == 1 && repeat <= PAD_LIMIT) {
- return padding(repeat, str.charAt(0));
+ return padding(repeat, str.charAt(0));
}
int outputLength = inputLength * repeat;
switch (inputLength) {
- case 1:
+ case 1 :
char ch = str.charAt(0);
char[] output1 = new char[outputLength];
for (int i = repeat - 1; i >= 0; i--) {
output1[i] = ch;
}
return new String(output1);
- case 2:
+ case 2 :
char ch0 = str.charAt(0);
char ch1 = str.charAt(1);
char[] output2 = new char[outputLength];
- for (int i = repeat * 2 - 2; i >= 0; i--,i--) {
+ for (int i = repeat * 2 - 2; i >= 0; i--, i--) {
output2[i] = ch0;
output2[i + 1] = ch1;
}
return new String(output2);
- default:
- StringBuffer buf = new StringBuffer(outputLength);
+ default :
+ StrBuilder buf = new StrBuilder(outputLength);
for (int i = 0; i < repeat; i++) {
buf.append(str);
- }
+ }
return buf.toString();
}
}
/**
+ * Repeat a String repeat
times to form a
+ * new String, with a String separator injected each time.
+ *
+ *
+ * StringUtils.repeat(null, null, 2) = null
+ * StringUtils.repeat(null, "x", 2) = null
+ * StringUtils.repeat("", null, 0) = ""
+ * StringUtils.repeat("", "", 2) = ""
+ * StringUtils.repeat("", "x", 3) = "xxx"
+ * StringUtils.repeat("?", ", ", 3) = "?, ?, ?"
+ *
+ *
+ * @param str the String to repeat, may be null
+ * @param separator the String to inject, may be null
+ * @param repeat number of times to repeat str, negative treated as zero
+ * @return a new String consisting of the original String repeated,
+ * null
if null String input
+ * @since 2.5
+ */
+ public static String repeat(String str, String separator, int repeat) {
+ if(str == null || separator == null) {
+ return repeat(str, repeat);
+ } else {
+ // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it
+ String result = repeat(str + separator, repeat);
+ return removeEnd(result, separator);
+ }
+ }
+
+ /**
* Returns padding using the specified delimiter repeated
* to a given length.
*
@@ -3053,30 +4671,35 @@
* StringUtils.padding(-2, 'e') = IndexOutOfBoundsException
*
*
+ * Note: this method doesn't not support padding with
+ * Unicode Supplementary Characters
+ * as they require a pair of char
s to be represented.
+ * If you are needing to support full I18N of your applications
+ * consider using {@link #repeat(String, int)} instead.
+ *
+ *
* @param repeat number of times to repeat delim
* @param padChar character to repeat
* @return String with repeated character
* @throws IndexOutOfBoundsException if repeat < 0
+ * @see #repeat(String, int)
*/
- private static String padding(int repeat, char padChar) {
- // be careful of synchronization in this method
- // we are assuming that get and set from an array index is atomic
- String pad = PADDING[padChar];
- if (pad == null) {
- pad = String.valueOf(padChar);
+ private static String padding(int repeat, char padChar) throws IndexOutOfBoundsException {
+ if (repeat < 0) {
+ throw new IndexOutOfBoundsException("Cannot pad a negative amount: " + repeat);
}
- while (pad.length() < repeat) {
- pad = pad.concat(pad);
+ final char[] buf = new char[repeat];
+ for (int i = 0; i < buf.length; i++) {
+ buf[i] = padChar;
}
- PADDING[padChar] = pad;
- return pad.substring(0, repeat);
+ return new String(buf);
}
/**
* Right pad a String with spaces (' ').
*
* The String is padded to the size of size
.
- *
+ *
*
* StringUtils.rightPad(null, *) = null
* StringUtils.rightPad("", 3) = " "
@@ -3157,7 +4780,7 @@
if (str == null) {
return null;
}
- if (padStr == null || padStr.length() == 0) {
+ if (isEmpty(padStr)) {
padStr = " ";
}
int padLen = padStr.length();
@@ -3169,7 +4792,7 @@
if (padLen == 1 && pads <= PAD_LIMIT) {
return rightPad(str, size, padStr.charAt(0));
}
-
+
if (pads == padLen) {
return str.concat(padStr);
} else if (pads < padLen) {
@@ -3187,7 +4810,7 @@
/**
* Left pad a String with spaces (' ').
*
- * The String is padded to the size of size.
+ * The String is padded to the size of size
.
*
*
* StringUtils.leftPad(null, *) = null
@@ -3204,7 +4827,7 @@
* null
if null String input
*/
public static String leftPad(String str, int size) {
- return leftPad(str, size, ' ');
+ return leftPad(str, size, ' ');
}
/**
@@ -3269,7 +4892,7 @@
if (str == null) {
return null;
}
- if (padStr == null || padStr.length() == 0) {
+ if (isEmpty(padStr)) {
padStr = " ";
}
int padLen = padStr.length();
@@ -3281,7 +4904,7 @@
if (padLen == 1 && pads <= PAD_LIMIT) {
return leftPad(str, size, padStr.charAt(0));
}
-
+
if (pads == padLen) {
return padStr.concat(str);
} else if (pads < padLen) {
@@ -3296,12 +4919,24 @@
}
}
+ /**
+ * Gets a String's length or 0
if the String is null
.
+ *
+ * @param str
+ * a String or null
+ * @return String length or 0
if the String is null
.
+ * @since 2.4
+ */
+ public static int length(String str) {
+ return str == null ? 0 : str.length();
+ }
+
// Centering
//-----------------------------------------------------------------------
/**
* Centers a String in a larger String of size size
* using the space character (' ').
- *
+ *
*
If the size is less than the String length, the String is returned.
* A null
String returns null
.
* A negative size is treated as zero.
@@ -3316,7 +4951,7 @@
* StringUtils.center("abcd", 2) = "abcd"
* StringUtils.center("a", 4) = " a "
*
- *
+ *
* @param str the String to center, may be null
* @param size the int size of new String, negative treated as zero
* @return centered String, null
if null String input
@@ -3342,7 +4977,7 @@
* StringUtils.center("a", 4, ' ') = " a "
* StringUtils.center("a", 4, 'y') = "yayy"
*
- *
+ *
* @param str the String to center, may be null
* @param size the int size of new String, negative treated as zero
* @param padChar the character to pad the new String with
@@ -3382,7 +5017,7 @@
* StringUtils.center("abc", 7, null) = " abc "
* StringUtils.center("abc", 7, "") = " abc "
*
- *
+ *
* @param str the String to center, may be null
* @param size the int size of new String, negative treated as zero
* @param padStr the String to pad the new String with, must not be null or empty
@@ -3393,7 +5028,7 @@
if (str == null || size <= 0) {
return str;
}
- if (padStr == null || padStr.length() == 0) {
+ if (isEmpty(padStr)) {
padStr = " ";
}
int strLen = str.length();
@@ -3410,15 +5045,20 @@
//-----------------------------------------------------------------------
/**
* Converts a String to upper case as per {@link String#toUpperCase()}.
- *
+ *
* A null
input String returns null
.
- *
+ *
*
* StringUtils.upperCase(null) = null
* StringUtils.upperCase("") = ""
* StringUtils.upperCase("aBc") = "ABC"
*
- *
+ *
+ * Note: As described in the documentation for {@link String#toUpperCase()},
+ * the result of this method is affected by the current locale.
+ * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)}
+ * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).
+ *
* @param str the String to upper case, may be null
* @return the upper cased String, null
if null String input
*/
@@ -3430,16 +5070,44 @@
}
/**
+ * Converts a String to upper case as per {@link String#toUpperCase(Locale)}.
+ *
+ * A null
input String returns null
.
+ *
+ *
+ * StringUtils.upperCase(null, Locale.ENGLISH) = null
+ * StringUtils.upperCase("", Locale.ENGLISH) = ""
+ * StringUtils.upperCase("aBc", Locale.ENGLISH) = "ABC"
+ *
+ *
+ * @param str the String to upper case, may be null
+ * @param locale the locale that defines the case transformation rules, must not be null
+ * @return the upper cased String, null
if null String input
+ * @since 2.5
+ */
+ public static String upperCase(String str, Locale locale) {
+ if (str == null) {
+ return null;
+ }
+ return str.toUpperCase(locale);
+ }
+
+ /**
* Converts a String to lower case as per {@link String#toLowerCase()}.
- *
+ *
* A null
input String returns null
.
- *
+ *
*
* StringUtils.lowerCase(null) = null
* StringUtils.lowerCase("") = ""
* StringUtils.lowerCase("aBc") = "abc"
*
- *
+ *
+ * Note: As described in the documentation for {@link String#toLowerCase()},
+ * the result of this method is affected by the current locale.
+ * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)}
+ * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).
+ *
* @param str the String to lower case, may be null
* @return the lower cased String, null
if null String input
*/
@@ -3451,19 +5119,42 @@
}
/**
+ * Converts a String to lower case as per {@link String#toLowerCase(Locale)}.
+ *
+ * A null
input String returns null
.
+ *
+ *
+ * StringUtils.lowerCase(null, Locale.ENGLISH) = null
+ * StringUtils.lowerCase("", Locale.ENGLISH) = ""
+ * StringUtils.lowerCase("aBc", Locale.ENGLISH) = "abc"
+ *
+ *
+ * @param str the String to lower case, may be null
+ * @param locale the locale that defines the case transformation rules, must not be null
+ * @return the lower cased String, null
if null String input
+ * @since 2.5
+ */
+ public static String lowerCase(String str, Locale locale) {
+ if (str == null) {
+ return null;
+ }
+ return str.toLowerCase(locale);
+ }
+
+ /**
* Capitalizes a String changing the first letter to title case as
* per {@link Character#toTitleCase(char)}. No other letters are changed.
- *
- * For a word based alorithm, see {@link WordUtils#capitalize(String)}.
+ *
+ *
For a word based algorithm, see {@link WordUtils#capitalize(String)}.
* A null
input String returns null
.
- *
+ *
*
* StringUtils.capitalize(null) = null
* StringUtils.capitalize("") = ""
* StringUtils.capitalize("cat") = "Cat"
* StringUtils.capitalize("cAt") = "CAt"
*
- *
+ *
* @param str the String to capitalize, may be null
* @return the capitalized String, null
if null String input
* @see WordUtils#capitalize(String)
@@ -3475,7 +5166,7 @@
if (str == null || (strLen = str.length()) == 0) {
return str;
}
- return new StringBuffer(strLen)
+ return new StrBuilder(strLen)
.append(Character.toTitleCase(str.charAt(0)))
.append(str.substring(1))
.toString();
@@ -3484,7 +5175,7 @@
/**
* Capitalizes a String changing the first letter to title case as
* per {@link Character#toTitleCase(char)}. No other letters are changed.
- *
+ *
* @param str the String to capitalize, may be null
* @return the capitalized String, null
if null String input
* @deprecated Use the standardly named {@link #capitalize(String)}.
@@ -3497,17 +5188,17 @@
/**
* Uncapitalizes a String changing the first letter to title case as
* per {@link Character#toLowerCase(char)}. No other letters are changed.
- *
- * For a word based alorithm, see {@link WordUtils#uncapitalize(String)}.
+ *
+ *
For a word based algorithm, see {@link WordUtils#uncapitalize(String)}.
* A null
input String returns null
.
- *
+ *
*
* StringUtils.uncapitalize(null) = null
* StringUtils.uncapitalize("") = ""
* StringUtils.uncapitalize("Cat") = "cat"
* StringUtils.uncapitalize("CAT") = "cAT"
*
- *
+ *
* @param str the String to uncapitalize, may be null
* @return the uncapitalized String, null
if null String input
* @see WordUtils#uncapitalize(String)
@@ -3519,7 +5210,7 @@
if (str == null || (strLen = str.length()) == 0) {
return str;
}
- return new StringBuffer(strLen)
+ return new StrBuilder(strLen)
.append(Character.toLowerCase(str.charAt(0)))
.append(str.substring(1))
.toString();
@@ -3528,7 +5219,7 @@
/**
* Uncapitalizes a String changing the first letter to title case as
* per {@link Character#toLowerCase(char)}. No other letters are changed.
- *
+ *
* @param str the String to uncapitalize, may be null
* @return the uncapitalized String, null
if null String input
* @deprecated Use the standardly named {@link #uncapitalize(String)}.
@@ -3541,27 +5232,27 @@
/**
* Swaps the case of a String changing upper and title case to
* lower case, and lower case to upper case.
- *
+ *
*
* - Upper case character converts to Lower case
* - Title case character converts to Lower case
* - Lower case character converts to Upper case
*
- *
- * For a word based alorithm, see {@link WordUtils#swapCase(String)}.
+ *
+ *
For a word based algorithm, see {@link WordUtils#swapCase(String)}.
* A null
input String returns null
.
- *
+ *
*
* StringUtils.swapCase(null) = null
* StringUtils.swapCase("") = ""
* StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone"
*
- *
+ *
* NOTE: This method changed in Lang version 2.0.
- * It no longer performs a word based alorithm.
+ * It no longer performs a word based algorithm.
* If you only use ASCII, you will notice no change.
* That functionality is available in WordUtils.
- *
+ *
* @param str the String to swap case, may be null
* @return the changed String, null
if null String input
*/
@@ -3570,7 +5261,7 @@
if (str == null || (strLen = str.length()) == 0) {
return str;
}
- StringBuffer buffer = new StringBuffer(strLen);
+ StrBuilder buffer = new StrBuilder(strLen);
char ch = 0;
for (int i = 0; i < strLen; i++) {
@@ -3609,7 +5300,7 @@
* Counts how many times the substring appears in the larger String.
*
* A null
or empty ("") String input returns 0
.
- *
+ *
*
* StringUtils.countMatches(null, *) = 0
* StringUtils.countMatches("", *) = 0
@@ -3622,15 +5313,15 @@
*
* @param str the String to check, may be null
* @param sub the substring to count, may be null
- * @return the number of occurances, 0 if either String is null
+ * @return the number of occurrences, 0 if either String is null
*/
public static int countMatches(String str, String sub) {
- if (str == null || str.length() == 0 || sub == null || sub.length() == 0) {
+ if (isEmpty(str) || isEmpty(sub)) {
return 0;
}
int count = 0;
int idx = 0;
- while ((idx = str.indexOf(sub, idx)) != -1) {
+ while ((idx = str.indexOf(sub, idx)) != INDEX_NOT_FOUND) {
count++;
idx += sub.length();
}
@@ -3643,8 +5334,8 @@
* Checks if the String contains only unicode letters.
*
* null
will return false
.
- * An empty String ("") will return true
.
- *
+ * An empty String (length()=0) will return true
.
+ *
*
* StringUtils.isAlpha(null) = false
* StringUtils.isAlpha("") = true
@@ -3675,8 +5366,8 @@
* space (' ').
*
* null
will return false
- * An empty String ("") will return true
.
- *
+ * An empty String (length()=0) will return true
.
+ *
*
* StringUtils.isAlphaSpace(null) = false
* StringUtils.isAlphaSpace("") = true
@@ -3697,8 +5388,7 @@
}
int sz = str.length();
for (int i = 0; i < sz; i++) {
- if ((Character.isLetter(str.charAt(i)) == false) &&
- (str.charAt(i) != ' ')) {
+ if ((Character.isLetter(str.charAt(i)) == false) && (str.charAt(i) != ' ')) {
return false;
}
}
@@ -3709,8 +5399,8 @@
* Checks if the String contains only unicode letters or digits.
*
* null
will return false
.
- * An empty String ("") will return true
.
- *
+ * An empty String (length()=0) will return true
.
+ *
*
* StringUtils.isAlphanumeric(null) = false
* StringUtils.isAlphanumeric("") = true
@@ -3743,8 +5433,8 @@
* or space (' '
).
*
* null
will return false
.
- * An empty String ("") will return true
.
- *
+ * An empty String (length()=0) will return true
.
+ *
*
* StringUtils.isAlphanumeric(null) = false
* StringUtils.isAlphanumeric("") = true
@@ -3765,21 +5455,58 @@
}
int sz = str.length();
for (int i = 0; i < sz; i++) {
- if ((Character.isLetterOrDigit(str.charAt(i)) == false) &&
- (str.charAt(i) != ' ')) {
+ if ((Character.isLetterOrDigit(str.charAt(i)) == false) && (str.charAt(i) != ' ')) {
return false;
}
}
return true;
}
/**
+ * Checks if the string contains only ASCII printable characters.
+ *
+ * null
will return false
.
+ * An empty String (length()=0) will return true
.
+ *
+ *
+ * StringUtils.isAsciiPrintable(null) = false
+ * StringUtils.isAsciiPrintable("") = true
+ * StringUtils.isAsciiPrintable(" ") = true
+ * StringUtils.isAsciiPrintable("Ceki") = true
+ * StringUtils.isAsciiPrintable("ab2c") = true
+ * StringUtils.isAsciiPrintable("!ab-c~") = true
+ * StringUtils.isAsciiPrintable("\u0020") = true
+ * StringUtils.isAsciiPrintable("\u0021") = true
+ * StringUtils.isAsciiPrintable("\u007e") = true
+ * StringUtils.isAsciiPrintable("\u007f") = false
+ * StringUtils.isAsciiPrintable("Ceki G\u00fclc\u00fc") = false
+ *
+ *
+ * @param str the string to check, may be null
+ * @return true
if every character is in the range
+ * 32 thru 126
+ * @since 2.1
+ */
+ public static boolean isAsciiPrintable(String str) {
+ if (str == null) {
+ return false;
+ }
+ int sz = str.length();
+ for (int i = 0; i < sz; i++) {
+ if (CharUtils.isAsciiPrintable(str.charAt(i)) == false) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
* Checks if the String contains only unicode digits.
* A decimal point is not a unicode digit and returns false.
*
* null
will return false
.
- * An empty String ("") will return true
.
- *
+ * An empty String (length()=0) will return true
.
+ *
*
* StringUtils.isNumeric(null) = false
* StringUtils.isNumeric("") = true
@@ -3813,8 +5540,8 @@
* A decimal point is not a unicode digit and returns false.
*
* null
will return false
.
- * An empty String ("") will return true
.
- *
+ * An empty String (length()=0) will return true
.
+ *
*
* StringUtils.isNumeric(null) = false
* StringUtils.isNumeric("") = true
@@ -3836,8 +5563,7 @@
}
int sz = str.length();
for (int i = 0; i < sz; i++) {
- if ((Character.isDigit(str.charAt(i)) == false) &&
- (str.charAt(i) != ' ')) {
+ if ((Character.isDigit(str.charAt(i)) == false) && (str.charAt(i) != ' ')) {
return false;
}
}
@@ -3848,8 +5574,8 @@
* Checks if the String contains only whitespace.
*
* null
will return false
.
- * An empty String ("") will return true
.
- *
+ * An empty String (length()=0) will return true
.
+ *
*
* StringUtils.isWhitespace(null) = false
* StringUtils.isWhitespace("") = true
@@ -3869,77 +5595,182 @@
}
int sz = str.length();
for (int i = 0; i < sz; i++) {
- if ((Character.isWhitespace(str.charAt(i)) == false) ) {
+ if ((Character.isWhitespace(str.charAt(i)) == false)) {
return false;
}
}
return true;
}
+ /**
+ * Checks if the String contains only lowercase characters.
+ *
+ * null
will return false
.
+ * An empty String (length()=0) will return false
.
+ *
+ *
+ * StringUtils.isAllLowerCase(null) = false
+ * StringUtils.isAllLowerCase("") = false
+ * StringUtils.isAllLowerCase(" ") = false
+ * StringUtils.isAllLowerCase("abc") = true
+ * StringUtils.isAllLowerCase("abC") = false
+ *
+ *
+ * @param str the String to check, may be null
+ * @return true
if only contains lowercase characters, and is non-null
+ * @since 2.5
+ */
+ public static boolean isAllLowerCase(String str) {
+ if (str == null || isEmpty(str)) {
+ return false;
+ }
+ int sz = str.length();
+ for (int i = 0; i < sz; i++) {
+ if (Character.isLowerCase(str.charAt(i)) == false) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks if the String contains only uppercase characters.
+ *
+ * null
will return false
.
+ * An empty String (length()=0) will return false
.
+ *
+ *
+ * StringUtils.isAllUpperCase(null) = false
+ * StringUtils.isAllUpperCase("") = false
+ * StringUtils.isAllUpperCase(" ") = false
+ * StringUtils.isAllUpperCase("ABC") = true
+ * StringUtils.isAllUpperCase("aBC") = false
+ *
+ *
+ * @param str the String to check, may be null
+ * @return true
if only contains uppercase characters, and is non-null
+ * @since 2.5
+ */
+ public static boolean isAllUpperCase(String str) {
+ if (str == null || isEmpty(str)) {
+ return false;
+ }
+ int sz = str.length();
+ for (int i = 0; i < sz; i++) {
+ if (Character.isUpperCase(str.charAt(i)) == false) {
+ return false;
+ }
+ }
+ return true;
+ }
+
// Defaults
//-----------------------------------------------------------------------
/**
- * Returns either the passed in String,
+ *
Returns either the passed in String,
* or if the String is null
, an empty String ("").
- *
+ *
*
* StringUtils.defaultString(null) = ""
* StringUtils.defaultString("") = ""
* StringUtils.defaultString("bat") = "bat"
*
- *
+ *
* @see ObjectUtils#toString(Object)
* @see String#valueOf(Object)
* @param str the String to check, may be null
* @return the passed in String, or the empty String if it
* was null
*/
public static String defaultString(String str) {
- return (str == null ? EMPTY : str);
+ return str == null ? EMPTY : str;
}
/**
- * Returns either the passed in String,
- * or if the String is null
, an empty String ("").
- *
+ * Returns either the passed in String, or if the String is
+ * null
, the value of defaultStr
.
+ *
*
- * StringUtils.defaultString(null, "null") = "null"
- * StringUtils.defaultString("", "null") = ""
- * StringUtils.defaultString("bat", "null") = "bat"
+ * StringUtils.defaultString(null, "NULL") = "NULL"
+ * StringUtils.defaultString("", "NULL") = ""
+ * StringUtils.defaultString("bat", "NULL") = "bat"
*
- *
+ *
* @see ObjectUtils#toString(Object,String)
* @see String#valueOf(Object)
* @param str the String to check, may be null
- * @param defaultStr the default String to return
+ * @param defaultStr the default String to return
* if the input is null
, may be null
* @return the passed in String, or the default if it was null
*/
public static String defaultString(String str, String defaultStr) {
- return (str == null ? defaultStr : str);
+ return str == null ? defaultStr : str;
}
+ /**
+ * Returns either the passed in String, or if the String is
+ * whitespace, empty ("") or null
, the value of defaultStr
.
+ *
+ *
+ * StringUtils.defaultIfBlank(null, "NULL") = "NULL"
+ * StringUtils.defaultIfBlank("", "NULL") = "NULL"
+ * StringUtils.defaultIfBlank(" ", "NULL") = "NULL"
+ * StringUtils.defaultIfBlank("bat", "NULL") = "bat"
+ * StringUtils.defaultIfBlank("", null) = null
+ *
+ * @param str the String to check, may be null
+ * @param defaultStr the default String to return
+ * if the input is whitespace, empty ("") or null
, may be null
+ * @return the passed in String, or the default
+ * @see StringUtils#defaultString(String, String)
+ * @since 2.6
+ */
+ public static String defaultIfBlank(String str, String defaultStr) {
+ return StringUtils.isBlank(str) ? defaultStr : str;
+ }
+
+ /**
+ * Returns either the passed in String, or if the String is
+ * empty or null
, the value of defaultStr
.
+ *
+ *
+ * StringUtils.defaultIfEmpty(null, "NULL") = "NULL"
+ * StringUtils.defaultIfEmpty("", "NULL") = "NULL"
+ * StringUtils.defaultIfEmpty("bat", "NULL") = "bat"
+ * StringUtils.defaultIfEmpty("", null) = null
+ *
+ *
+ * @param str the String to check, may be null
+ * @param defaultStr the default String to return
+ * if the input is empty ("") or null
, may be null
+ * @return the passed in String, or the default
+ * @see StringUtils#defaultString(String, String)
+ */
+ public static String defaultIfEmpty(String str, String defaultStr) {
+ return StringUtils.isEmpty(str) ? defaultStr : str;
+ }
+
// Reversing
//-----------------------------------------------------------------------
/**
- * Reverses a String as per {@link StringBuffer#reverse()}.
+ * Reverses a String as per {@link StrBuilder#reverse()}.
*
- *
String returns null
.
- *
+ * A null
String returns null
.
+ *
*
* StringUtils.reverse(null) = null
* StringUtils.reverse("") = ""
* StringUtils.reverse("bat") = "tab"
*
- *
+ *
* @param str the String to reverse, may be null
* @return the reversed String, null
if null String input
*/
public static String reverse(String str) {
if (str == null) {
return null;
}
- return new StringBuffer(str).reverse().toString();
+ return new StrBuilder(str).reverse().toString();
}
/**
@@ -3948,14 +5779,14 @@
* The Strings between the delimiters are not reversed.
* Thus java.lang.String becomes String.lang.java (if the delimiter
* is '.'
).
- *
+ *
*
* StringUtils.reverseDelimited(null, *) = null
* StringUtils.reverseDelimited("", *) = ""
* StringUtils.reverseDelimited("a.b.c", 'x') = "a.b.c"
* StringUtils.reverseDelimited("a.b.c", ".") = "c.b.a"
*
- *
+ *
* @param str the String to reverse, may be null
* @param separatorChar the separator character to use
* @return the reversed String, null
if null String input
@@ -3965,7 +5796,7 @@
if (str == null) {
return null;
}
- // could implement manually, but simple way is to reuse other,
+ // could implement manually, but simple way is to reuse other,
// probably slower, methods.
String[] strs = split(str, separatorChar);
ArrayUtils.reverse(strs);
@@ -3978,27 +5809,27 @@
* The Strings between the delimiters are not reversed.
* Thus java.lang.String becomes String.lang.java (if the delimiter
* is "."
).
- *
+ *
*
* StringUtils.reverseDelimitedString(null, *) = null
* StringUtils.reverseDelimitedString("",*) = ""
* StringUtils.reverseDelimitedString("a.b.c", null) = "a.b.c"
* StringUtils.reverseDelimitedString("a.b.c", ".") = "c.b.a"
*
- *
+ *
* @param str the String to reverse, may be null
* @param separatorChars the separator characters to use, null treated as whitespace
* @return the reversed String, null
if null String input
* @deprecated Use {@link #reverseDelimited(String, char)} instead.
* This method is broken as the join doesn't know which char to use.
* Method will be removed in Commons Lang 3.0.
- *
+ *
*/
public static String reverseDelimitedString(String str, String separatorChars) {
if (str == null) {
return null;
}
- // could implement manually, but simple way is to reuse other,
+ // could implement manually, but simple way is to reuse other,
// probably slower, methods.
String[] strs = split(str, separatorChars);
ArrayUtils.reverse(strs);
@@ -4011,7 +5842,7 @@
// Abbreviating
//-----------------------------------------------------------------------
/**
- * Abbreviates a String using ellipses. This will turn
+ *
Abbreviates a String using ellipses. This will turn
* "Now is the time for all good men" into "Now is the time for..."
*
* Specifically:
@@ -4047,7 +5878,7 @@
}
/**
- *
Abbreviates a String using ellipses. This will turn
+ *
Abbreviates a String using ellipses. This will turn
* "Now is the time for all good men" into "...is the time for..."
*
* Works like abbreviate(String, int)
, but allows you to specify
@@ -4108,7 +5939,57 @@
}
return "..." + str.substring(str.length() - (maxWidth - 3));
}
+
+ /**
+ *
Abbreviates a String to the length passed, replacing the middle characters with the supplied
+ * replacement String.
+ *
+ * This abbreviation only occurs if the following criteria is met:
+ *
+ * - Neither the String for abbreviation nor the replacement String are null or empty
+ * - The length to truncate to is less than the length of the supplied String
+ * - The length to truncate to is greater than 0
+ * - The abbreviated String will have enough room for the length supplied replacement String
+ * and the first and last characters of the supplied String for abbreviation
+ *
+ * Otherwise, the returned String will be the same as the supplied String for abbreviation.
+ *
+ *
+ *
+ * StringUtils.abbreviateMiddle(null, null, 0) = null
+ * StringUtils.abbreviateMiddle("abc", null, 0) = "abc"
+ * StringUtils.abbreviateMiddle("abc", ".", 0) = "abc"
+ * StringUtils.abbreviateMiddle("abc", ".", 3) = "abc"
+ * StringUtils.abbreviateMiddle("abcdef", ".", 4) = "ab.f"
+ *
+ *
+ * @param str the String to abbreviate, may be null
+ * @param middle the String to replace the middle characters with, may be null
+ * @param length the length to abbreviate str
to.
+ * @return the abbreviated String if the above criteria is met, or the original String supplied for abbreviation.
+ * @since 2.5
+ */
+ public static String abbreviateMiddle(String str, String middle, int length) {
+ if (isEmpty(str) || isEmpty(middle)) {
+ return str;
+ }
+
+ if (length >= str.length() || length < (middle.length()+2)) {
+ return str;
+ }
+ int targetSting = length-middle.length();
+ int startOffset = targetSting/2+targetSting%2;
+ int endOffset = str.length()-targetSting/2;
+
+ StrBuilder builder = new StrBuilder(length);
+ builder.append(str.substring(0,startOffset));
+ builder.append(middle);
+ builder.append(str.substring(endOffset));
+
+ return builder.toString();
+ }
+
// Difference
//-----------------------------------------------------------------------
/**
@@ -4132,7 +6013,7 @@
*
* @param str1 the first String, may be null
* @param str2 the second String, may be null
- * @return the portion of str2 where it differs from str1; returns the
+ * @return the portion of str2 where it differs from str1; returns the
* empty String if they are equal
* @since 2.0
*/
@@ -4144,7 +6025,7 @@
return str1;
}
int at = indexOfDifference(str1, str2);
- if (at == -1) {
+ if (at == INDEX_NOT_FOUND) {
return EMPTY;
}
return str2.substring(at);
@@ -4153,8 +6034,8 @@
/**
* Compares two Strings, and returns the index at which the
* Strings begin to differ.
- *
- * For example,
+ *
+ *
For example,
* indexOfDifference("i am a machine", "i am a robot") -> 7
*
*
@@ -4175,7 +6056,7 @@
*/
public static int indexOfDifference(String str1, String str2) {
if (str1 == str2) {
- return -1;
+ return INDEX_NOT_FOUND;
}
if (str1 == null || str2 == null) {
return 0;
@@ -4189,22 +6070,168 @@
if (i < str2.length() || i < str1.length()) {
return i;
}
- return -1;
+ return INDEX_NOT_FOUND;
}
+ /**
+ * Compares all Strings in an array and returns the index at which the
+ * Strings begin to differ.
+ *
+ * For example,
+ * indexOfDifference(new String[] {"i am a machine", "i am a robot"}) -> 7
+ *
+ *
+ * StringUtils.indexOfDifference(null) = -1
+ * StringUtils.indexOfDifference(new String[] {}) = -1
+ * StringUtils.indexOfDifference(new String[] {"abc"}) = -1
+ * StringUtils.indexOfDifference(new String[] {null, null}) = -1
+ * StringUtils.indexOfDifference(new String[] {"", ""}) = -1
+ * StringUtils.indexOfDifference(new String[] {"", null}) = 0
+ * StringUtils.indexOfDifference(new String[] {"abc", null, null}) = 0
+ * StringUtils.indexOfDifference(new String[] {null, null, "abc"}) = 0
+ * StringUtils.indexOfDifference(new String[] {"", "abc"}) = 0
+ * StringUtils.indexOfDifference(new String[] {"abc", ""}) = 0
+ * StringUtils.indexOfDifference(new String[] {"abc", "abc"}) = -1
+ * StringUtils.indexOfDifference(new String[] {"abc", "a"}) = 1
+ * StringUtils.indexOfDifference(new String[] {"ab", "abxyz"}) = 2
+ * StringUtils.indexOfDifference(new String[] {"abcde", "abxyz"}) = 2
+ * StringUtils.indexOfDifference(new String[] {"abcde", "xyz"}) = 0
+ * StringUtils.indexOfDifference(new String[] {"xyz", "abcde"}) = 0
+ * StringUtils.indexOfDifference(new String[] {"i am a machine", "i am a robot"}) = 7
+ *
+ *
+ * @param strs array of strings, entries may be null
+ * @return the index where the strings begin to differ; -1 if they are all equal
+ * @since 2.4
+ */
+ public static int indexOfDifference(String[] strs) {
+ if (strs == null || strs.length <= 1) {
+ return INDEX_NOT_FOUND;
+ }
+ boolean anyStringNull = false;
+ boolean allStringsNull = true;
+ int arrayLen = strs.length;
+ int shortestStrLen = Integer.MAX_VALUE;
+ int longestStrLen = 0;
+ // find the min and max string lengths; this avoids checking to make
+ // sure we are not exceeding the length of the string each time through
+ // the bottom loop.
+ for (int i = 0; i < arrayLen; i++) {
+ if (strs[i] == null) {
+ anyStringNull = true;
+ shortestStrLen = 0;
+ } else {
+ allStringsNull = false;
+ shortestStrLen = Math.min(strs[i].length(), shortestStrLen);
+ longestStrLen = Math.max(strs[i].length(), longestStrLen);
+ }
+ }
+
+ // handle lists containing all nulls or all empty strings
+ if (allStringsNull || (longestStrLen == 0 && !anyStringNull)) {
+ return INDEX_NOT_FOUND;
+ }
+
+ // handle lists containing some nulls or some empty strings
+ if (shortestStrLen == 0) {
+ return 0;
+ }
+
+ // find the position with the first difference across all strings
+ int firstDiff = -1;
+ for (int stringPos = 0; stringPos < shortestStrLen; stringPos++) {
+ char comparisonChar = strs[0].charAt(stringPos);
+ for (int arrayPos = 1; arrayPos < arrayLen; arrayPos++) {
+ if (strs[arrayPos].charAt(stringPos) != comparisonChar) {
+ firstDiff = stringPos;
+ break;
+ }
+ }
+ if (firstDiff != -1) {
+ break;
+ }
+ }
+
+ if (firstDiff == -1 && shortestStrLen != longestStrLen) {
+ // we compared all of the characters up to the length of the
+ // shortest string and didn't find a match, but the string lengths
+ // vary, so return the length of the shortest string.
+ return shortestStrLen;
+ }
+ return firstDiff;
+ }
+
+ /**
+ * Compares all Strings in an array and returns the initial sequence of
+ * characters that is common to all of them.
+ *
+ * For example,
+ * getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) -> "i am a "
+ *
+ *
+ * StringUtils.getCommonPrefix(null) = ""
+ * StringUtils.getCommonPrefix(new String[] {}) = ""
+ * StringUtils.getCommonPrefix(new String[] {"abc"}) = "abc"
+ * StringUtils.getCommonPrefix(new String[] {null, null}) = ""
+ * StringUtils.getCommonPrefix(new String[] {"", ""}) = ""
+ * StringUtils.getCommonPrefix(new String[] {"", null}) = ""
+ * StringUtils.getCommonPrefix(new String[] {"abc", null, null}) = ""
+ * StringUtils.getCommonPrefix(new String[] {null, null, "abc"}) = ""
+ * StringUtils.getCommonPrefix(new String[] {"", "abc"}) = ""
+ * StringUtils.getCommonPrefix(new String[] {"abc", ""}) = ""
+ * StringUtils.getCommonPrefix(new String[] {"abc", "abc"}) = "abc"
+ * StringUtils.getCommonPrefix(new String[] {"abc", "a"}) = "a"
+ * StringUtils.getCommonPrefix(new String[] {"ab", "abxyz"}) = "ab"
+ * StringUtils.getCommonPrefix(new String[] {"abcde", "abxyz"}) = "ab"
+ * StringUtils.getCommonPrefix(new String[] {"abcde", "xyz"}) = ""
+ * StringUtils.getCommonPrefix(new String[] {"xyz", "abcde"}) = ""
+ * StringUtils.getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) = "i am a "
+ *
+ *
+ * @param strs array of String objects, entries may be null
+ * @return the initial sequence of characters that are common to all Strings
+ * in the array; empty String if the array is null, the elements are all null
+ * or if there is no common prefix.
+ * @since 2.4
+ */
+ public static String getCommonPrefix(String[] strs) {
+ if (strs == null || strs.length == 0) {
+ return EMPTY;
+ }
+ int smallestIndexOfDiff = indexOfDifference(strs);
+ if (smallestIndexOfDiff == INDEX_NOT_FOUND) {
+ // all strings were identical
+ if (strs[0] == null) {
+ return EMPTY;
+ }
+ return strs[0];
+ } else if (smallestIndexOfDiff == 0) {
+ // there were no common initial characters
+ return EMPTY;
+ } else {
+ // we found a common initial character sequence
+ return strs[0].substring(0, smallestIndexOfDiff);
+ }
+ }
+
// Misc
//-----------------------------------------------------------------------
/**
* Find the Levenshtein distance between two Strings.
*
* This is the number of changes needed to change one String into
- * another, where each change is a single character modification (deletion,
+ * another, where each change is a single character modification (deletion,
* insertion or substitution).
*
- * This implementation of the Levenshtein distance algorithm
- * is from http://www.merriampark.com/ld.htm
+ * The previous implementation of the Levenshtein distance algorithm
+ * was from http://www.merriampark.com/ld.htm
*
+ * Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError
+ * which can occur when my Java implementation is used with very large strings.
+ * This implementation of the Levenshtein distance algorithm
+ * is from http://www.merriampark.com/ldjava.htm
+ *
*
* StringUtils.getLevenshteinDistance(null, *) = IllegalArgumentException
* StringUtils.getLevenshteinDistance(*, null) = IllegalArgumentException
@@ -4218,7 +6245,7 @@
* StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8
* StringUtils.getLevenshteinDistance("hello", "hallo") = 1
*
- *
+ *
* @param s the first String, must not be null
* @param t the second String, must not be null
* @return result distance
@@ -4228,77 +6255,340 @@
if (s == null || t == null) {
throw new IllegalArgumentException("Strings must not be null");
}
- int d[][]; // matrix
- int n; // length of s
- int m; // length of t
- int i; // iterates through s
- int j; // iterates through t
- char s_i; // ith character of s
- char t_j; // jth character of t
- int cost; // cost
- // Step 1
- n = s.length();
- m = t.length();
+ /*
+ The difference between this impl. and the previous is that, rather
+ than creating and retaining a matrix of size s.length()+1 by t.length()+1,
+ we maintain two single-dimensional arrays of length s.length()+1. The first, d,
+ is the 'current working' distance array that maintains the newest distance cost
+ counts as we iterate through the characters of String s. Each time we increment
+ the index of String t we are comparing, d is copied to p, the second int[]. Doing so
+ allows us to retain the previous cost counts as required by the algorithm (taking
+ the minimum of the cost count to the left, up one, and diagonally up and to the left
+ of the current cost count being calculated). (Note that the arrays aren't really
+ copied anymore, just switched...this is clearly much better than cloning an array
+ or doing a System.arraycopy() each time through the outer loop.)
+
+ Effectively, the difference between the two implementations is this one does not
+ cause an out of memory condition when calculating the LD over two very large strings.
+ */
+
+ int n = s.length(); // length of s
+ int m = t.length(); // length of t
+
if (n == 0) {
return m;
- }
- if (m == 0) {
+ } else if (m == 0) {
return n;
}
- d = new int[n + 1][m + 1];
- // Step 2
- for (i = 0; i <= n; i++) {
- d[i][0] = i;
+ if (n > m) {
+ // swap the input strings to consume less memory
+ String tmp = s;
+ s = t;
+ t = tmp;
+ n = m;
+ m = t.length();
}
- for (j = 0; j <= m; j++) {
- d[0][j] = j;
+ int p[] = new int[n+1]; //'previous' cost array, horizontally
+ int d[] = new int[n+1]; // cost array, horizontally
+ int _d[]; //placeholder to assist in swapping p and d
+
+ // indexes into strings s and t
+ int i; // iterates through s
+ int j; // iterates through t
+
+ char t_j; // jth character of t
+
+ int cost; // cost
+
+ for (i = 0; i<=n; i++) {
+ p[i] = i;
}
- // Step 3
- for (i = 1; i <= n; i++) {
- s_i = s.charAt(i - 1);
+ for (j = 1; j<=m; j++) {
+ t_j = t.charAt(j-1);
+ d[0] = j;
- // Step 4
- for (j = 1; j <= m; j++) {
- t_j = t.charAt(j - 1);
+ for (i=1; i<=n; i++) {
+ cost = s.charAt(i-1)==t_j ? 0 : 1;
+ // minimum of cell to the left+1, to the top+1, diagonally left and up +cost
+ d[i] = Math.min(Math.min(d[i-1]+1, p[i]+1), p[i-1]+cost);
+ }
- // Step 5
- if (s_i == t_j) {
- cost = 0;
- } else {
- cost = 1;
- }
+ // copy current distance counts to 'previous row' distance counts
+ _d = p;
+ p = d;
+ d = _d;
+ }
- // Step 6
- d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost);
+ // our last action in the above loop was to switch d and p, so p now
+ // actually has the most recent cost counts
+ return p[n];
+ }
+
+ // startsWith
+ //-----------------------------------------------------------------------
+
+ /**
+ * Check if a String starts with a specified prefix.
+ *
+ * null
s are handled without exceptions. Two null
+ * references are considered to be equal. The comparison is case sensitive.
+ *
+ *
+ * StringUtils.startsWith(null, null) = true
+ * StringUtils.startsWith(null, "abc") = false
+ * StringUtils.startsWith("abcdef", null) = false
+ * StringUtils.startsWith("abcdef", "abc") = true
+ * StringUtils.startsWith("ABCDEF", "abc") = false
+ *
+ *
+ * @see java.lang.String#startsWith(String)
+ * @param str the String to check, may be null
+ * @param prefix the prefix to find, may be null
+ * @return true
if the String starts with the prefix, case sensitive, or
+ * both null
+ * @since 2.4
+ */
+ public static boolean startsWith(String str, String prefix) {
+ return startsWith(str, prefix, false);
+ }
+
+ /**
+ * Case insensitive check if a String starts with a specified prefix.
+ *
+ * null
s are handled without exceptions. Two null
+ * references are considered to be equal. The comparison is case insensitive.
+ *
+ *
+ * StringUtils.startsWithIgnoreCase(null, null) = true
+ * StringUtils.startsWithIgnoreCase(null, "abc") = false
+ * StringUtils.startsWithIgnoreCase("abcdef", null) = false
+ * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true
+ * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true
+ *
+ *
+ * @see java.lang.String#startsWith(String)
+ * @param str the String to check, may be null
+ * @param prefix the prefix to find, may be null
+ * @return true
if the String starts with the prefix, case insensitive, or
+ * both null
+ * @since 2.4
+ */
+ public static boolean startsWithIgnoreCase(String str, String prefix) {
+ return startsWith(str, prefix, true);
+ }
+
+ /**
+ * Check if a String starts with a specified prefix (optionally case insensitive).
+ *
+ * @see java.lang.String#startsWith(String)
+ * @param str the String to check, may be null
+ * @param prefix the prefix to find, may be null
+ * @param ignoreCase inidicates whether the compare should ignore case
+ * (case insensitive) or not.
+ * @return true
if the String starts with the prefix or
+ * both null
+ */
+ private static boolean startsWith(String str, String prefix, boolean ignoreCase) {
+ if (str == null || prefix == null) {
+ return (str == null && prefix == null);
+ }
+ if (prefix.length() > str.length()) {
+ return false;
+ }
+ return str.regionMatches(ignoreCase, 0, prefix, 0, prefix.length());
+ }
+
+ /**
+ * Check if a String starts with any of an array of specified strings.
+ *
+ *
+ * StringUtils.startsWithAny(null, null) = false
+ * StringUtils.startsWithAny(null, new String[] {"abc"}) = false
+ * StringUtils.startsWithAny("abcxyz", null) = false
+ * StringUtils.startsWithAny("abcxyz", new String[] {""}) = false
+ * StringUtils.startsWithAny("abcxyz", new String[] {"abc"}) = true
+ * StringUtils.startsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
+ *
+ *
+ * @see #startsWith(String, String)
+ * @param string the String to check, may be null
+ * @param searchStrings the Strings to find, may be null or empty
+ * @return true
if the String starts with any of the the prefixes, case insensitive, or
+ * both null
+ * @since 2.5
+ */
+ public static boolean startsWithAny(String string, String[] searchStrings) {
+ if (isEmpty(string) || ArrayUtils.isEmpty(searchStrings)) {
+ return false;
+ }
+ for (int i = 0; i < searchStrings.length; i++) {
+ String searchString = searchStrings[i];
+ if (StringUtils.startsWith(string, searchString)) {
+ return true;
}
}
+ return false;
+ }
- // Step 7
- return d[n][m];
+ // endsWith
+ //-----------------------------------------------------------------------
+
+ /**
+ * Check if a String ends with a specified suffix.
+ *
+ * null
s are handled without exceptions. Two null
+ * references are considered to be equal. The comparison is case sensitive.
+ *
+ *
+ * StringUtils.endsWith(null, null) = true
+ * StringUtils.endsWith(null, "def") = false
+ * StringUtils.endsWith("abcdef", null) = false
+ * StringUtils.endsWith("abcdef", "def") = true
+ * StringUtils.endsWith("ABCDEF", "def") = false
+ * StringUtils.endsWith("ABCDEF", "cde") = false
+ *
+ *
+ * @see java.lang.String#endsWith(String)
+ * @param str the String to check, may be null
+ * @param suffix the suffix to find, may be null
+ * @return true
if the String ends with the suffix, case sensitive, or
+ * both null
+ * @since 2.4
+ */
+ public static boolean endsWith(String str, String suffix) {
+ return endsWith(str, suffix, false);
}
/**
- * Gets the minimum of three int
values.
+ * Case insensitive check if a String ends with a specified suffix.
+ *
+ * null
s are handled without exceptions. Two null
+ * references are considered to be equal. The comparison is case insensitive.
+ *
+ *
+ * StringUtils.endsWithIgnoreCase(null, null) = true
+ * StringUtils.endsWithIgnoreCase(null, "def") = false
+ * StringUtils.endsWithIgnoreCase("abcdef", null) = false
+ * StringUtils.endsWithIgnoreCase("abcdef", "def") = true
+ * StringUtils.endsWithIgnoreCase("ABCDEF", "def") = true
+ * StringUtils.endsWithIgnoreCase("ABCDEF", "cde") = false
+ *
+ *
+ * @see java.lang.String#endsWith(String)
+ * @param str the String to check, may be null
+ * @param suffix the suffix to find, may be null
+ * @return true
if the String ends with the suffix, case insensitive, or
+ * both null
+ * @since 2.4
+ */
+ public static boolean endsWithIgnoreCase(String str, String suffix) {
+ return endsWith(str, suffix, true);
+ }
+
+ /**
+ * Check if a String ends with a specified suffix (optionally case insensitive).
+ *
+ * @see java.lang.String#endsWith(String)
+ * @param str the String to check, may be null
+ * @param suffix the suffix to find, may be null
+ * @param ignoreCase inidicates whether the compare should ignore case
+ * (case insensitive) or not.
+ * @return true
if the String starts with the prefix or
+ * both null
+ */
+ private static boolean endsWith(String str, String suffix, boolean ignoreCase) {
+ if (str == null || suffix == null) {
+ return (str == null && suffix == null);
+ }
+ if (suffix.length() > str.length()) {
+ return false;
+ }
+ int strOffset = str.length() - suffix.length();
+ return str.regionMatches(ignoreCase, strOffset, suffix, 0, suffix.length());
+ }
+
+ /**
+ *
+ * Similar to http://www.w3.org/TR/xpath/#function-normalize
+ * -space
+ *
+ *
+ * The function returns the argument string with whitespace normalized by using
+ * {@link #trim(String)}
to remove leading and trailing whitespace
+ * and then replacing sequences of whitespace characters by a single space.
+ *
+ * In XML Whitespace characters are the same as those allowed by the S production, which is S ::= (#x20 | #x9 | #xD | #xA)+
+ *
+ * See Java's {@link Character#isWhitespace(char)} for which characters are considered whitespace.
+ *
+ * The difference is that Java's whitespace includes vertical tab and form feed, which this functional will also
+ * normalize. Additonally {@link #trim(String)}
removes control characters (char <= 32) from both
+ * ends of this String.
+ *
+ *
+ * @see Character#isWhitespace(char)
+ * @see #trim(String)
+ * @see
+ * http://www.w3.org/TR/xpath/#function-normalize-space
+ * @param str the source String to normalize whitespaces from, may be null
+ * @return the modified string with whitespace normalized, null
if null String input
*
- * @param a value 1
- * @param b value 2
- * @param c value 3
- * @return the smallest of the values
+ * @since 2.6
*/
- private static int min(int a, int b, int c) {
- // Method copied from NumberUtils to avoid dependency on subpackage
- if (b < a) {
- a = b;
+ public static String normalizeSpace(String str) {
+ str = strip(str);
+ if(str == null || str.length() <= 2) {
+ return str;
}
- if (c < a) {
- a = c;
+ StrBuilder b = new StrBuilder(str.length());
+ for (int i = 0; i < str.length(); i++) {
+ char c = str.charAt(i);
+ if (Character.isWhitespace(c)) {
+ if (i > 0 && !Character.isWhitespace(str.charAt(i - 1))) {
+ b.append(' ');
+ }
+ } else {
+ b.append(c);
+ }
}
- return a;
+ return b.toString();
}
-}
+ /**
+ * Check if a String ends with any of an array of specified strings.
+ *
+ *
+ * StringUtils.endsWithAny(null, null) = false
+ * StringUtils.endsWithAny(null, new String[] {"abc"}) = false
+ * StringUtils.endsWithAny("abcxyz", null) = false
+ * StringUtils.endsWithAny("abcxyz", new String[] {""}) = true
+ * StringUtils.endsWithAny("abcxyz", new String[] {"xyz"}) = true
+ * StringUtils.endsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
+ *
+ *
+ * @param string the String to check, may be null
+ * @param searchStrings the Strings to find, may be null or empty
+ * @return true
if the String ends with any of the the prefixes, case insensitive, or
+ * both null
+ * @since 2.6
+ */
+ public static boolean endsWithAny(String string, String[] searchStrings) {
+ if (isEmpty(string) || ArrayUtils.isEmpty(searchStrings)) {
+ return false;
+ }
+ for (int i = 0; i < searchStrings.length; i++) {
+ String searchString = searchStrings[i];
+ if (StringUtils.endsWith(string, searchString)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/SystemUtils.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/SystemUtils.java (.../SystemUtils.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/SystemUtils.java (.../SystemUtils.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,720 +1,1392 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang;
+import java.io.File;
+
/**
- * Helpers for java.lang.System
.
+ *
+ * Helpers for java.lang.System
.
+ *
*
- * If a system property cannot be read due to security restrictions,
+ *
+ * If a system property cannot be read due to security restrictions,
* the corresponding field in this class will be set to null
- * and a message will be written to System.err
.
- *
+ * and a message will be written to System.err
.
+ *
+ *
+ *
+ * #ThreadSafe#
+ *
+ *
+ * @author Apache Software Foundation
* @author Based on code from Avalon Excalibur
* @author Based on code from Lucene
- * @author Stephen Colebourne
* @author Steve Downey
* @author Gary Gregory
* @author Michael Becke
* @author Tetsuya Kaneuchi
+ * @author Rafal Krupinski
+ * @author Jason Gritman
* @since 1.0
* @version $Id$
*/
public class SystemUtils {
+ private static final int JAVA_VERSION_TRIM_SIZE = 3;
+
+ /**
+ * The prefix String for all Windows OS.
+ */
+ private static final String OS_NAME_WINDOWS_PREFIX = "Windows";
+
// System property constants
- //-----------------------------------------------------------------------
+ // -----------------------------------------------------------------------
// These MUST be declared first. Other constants depend on this.
-
+
/**
- * The file.encoding
System Property.
- * File encoding, such as Cp1252
.
+ * The System property key for the user home directory.
+ */
+ private static final String USER_HOME_KEY = "user.home";
+
+ /**
+ * The System property key for the user directory.
+ */
+ private static final String USER_DIR_KEY = "user.dir";
+
+ /**
+ * The System property key for the Java IO temporary directory.
+ */
+ private static final String JAVA_IO_TMPDIR_KEY = "java.io.tmpdir";
+
+ /**
+ * The System property key for the Java home directory.
+ */
+ private static final String JAVA_HOME_KEY = "java.home";
+
+ /**
+ *
+ * The awt.toolkit
System Property.
+ *
+ *
+ * Holds a class name, on Windows XP this is sun.awt.windows.WToolkit
.
+ *
+ *
+ * On platforms without a GUI, this value is null
.
+ *
*
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
*
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will
+ * be out of sync with that System property.
+ *
+ *
+ * @since 2.1
+ */
+ public static final String AWT_TOOLKIT = getSystemProperty("awt.toolkit");
+
+ /**
+ *
+ * The file.encoding
System Property.
+ *
+ *
+ * File encoding, such as Cp1252
.
+ *
+ *
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since 2.0
- * @since Java 1.2.
+ * @since Java 1.2
*/
public static final String FILE_ENCODING = getSystemProperty("file.encoding");
/**
- * The file.separator
System Property.
- * File separator ("/"
on UNIX).
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The file.separator
System Property. File separator ("/"
on UNIX).
+ *
*
- * @since Java 1.1.
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
+ * @since Java 1.1
*/
public static final String FILE_SEPARATOR = getSystemProperty("file.separator");
/**
- * The java.class.path
System Property. Java class path.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The java.awt.fonts
System Property.
+ *
*
- * @since Java 1.1.
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
+ * @since 2.1
*/
+ public static final String JAVA_AWT_FONTS = getSystemProperty("java.awt.fonts");
+
+ /**
+ *
+ * The java.awt.graphicsenv
System Property.
+ *
+ *
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
+ * @since 2.1
+ */
+ public static final String JAVA_AWT_GRAPHICSENV = getSystemProperty("java.awt.graphicsenv");
+
+ /**
+ *
+ * The java.awt.headless
System Property.
+ * The value of this property is the String "true"
or "false"
.
+ *
+ *
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
+ * @see #isJavaAwtHeadless()
+ * @since 2.1
+ * @since Java 1.4
+ */
+ public static final String JAVA_AWT_HEADLESS = getSystemProperty("java.awt.headless");
+
+ /**
+ *
+ * The java.awt.printerjob
System Property.
+ *
+ *
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
+ * @since 2.1
+ */
+ public static final String JAVA_AWT_PRINTERJOB = getSystemProperty("java.awt.printerjob");
+
+ /**
+ *
+ * The java.class.path
System Property. Java class path.
+ *
+ *
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
+ * @since Java 1.1
+ */
public static final String JAVA_CLASS_PATH = getSystemProperty("java.class.path");
/**
- * The java.class.version
System Property.
- * Java class format version number.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The java.class.version
System Property. Java class format version number.
+ *
*
- * @since Java 1.1.
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
+ * @since Java 1.1
*/
public static final String JAVA_CLASS_VERSION = getSystemProperty("java.class.version");
/**
- * The java.compiler
System Property. Name of JIT compiler to use.
- * First in JDK version 1.2. Not used in Sun JDKs after 1.2.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The java.compiler
System Property. Name of JIT compiler to use.
+ * First in JDK version 1.2. Not used in Sun JDKs after 1.2.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.2. Not used in Sun versions after 1.2.
*/
public static final String JAVA_COMPILER = getSystemProperty("java.compiler");
/**
- * The java.ext.dirs
System Property. Path of extension directory
- * or directories.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The java.endorsed.dirs
System Property. Path of endorsed directory or directories.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
+ * @since Java 1.4
+ */
+ public static final String JAVA_ENDORSED_DIRS = getSystemProperty("java.endorsed.dirs");
+
+ /**
+ *
+ * The java.ext.dirs
System Property. Path of extension directory or directories.
+ *
+ *
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.3
*/
public static final String JAVA_EXT_DIRS = getSystemProperty("java.ext.dirs");
/**
- * The java.home
System Property. Java installation directory.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The java.home
System Property. Java installation directory.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.1
*/
- public static final String JAVA_HOME = getSystemProperty("java.home");
+ public static final String JAVA_HOME = getSystemProperty(JAVA_HOME_KEY);
/**
- * The java.io.tmpdir
System Property. Default temp file path.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The java.io.tmpdir
System Property. Default temp file path.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.2
*/
- public static final String JAVA_IO_TMPDIR = getSystemProperty("java.io.tmpdir");
+ public static final String JAVA_IO_TMPDIR = getSystemProperty(JAVA_IO_TMPDIR_KEY);
/**
- * The java.library.path
System Property. List of paths to search
- * when loading libraries.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The java.library.path
System Property. List of paths to search when loading libraries.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.2
*/
public static final String JAVA_LIBRARY_PATH = getSystemProperty("java.library.path");
/**
- * The java.runtime.name
System Property. Java Runtime Environment
- * name.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The java.runtime.name
System Property. Java Runtime Environment name.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since 2.0
* @since Java 1.3
*/
public static final String JAVA_RUNTIME_NAME = getSystemProperty("java.runtime.name");
/**
- * The java.runtime.version
System Property. Java Runtime Environment
- * version.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The java.runtime.version
System Property. Java Runtime Environment version.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since 2.0
* @since Java 1.3
*/
public static final String JAVA_RUNTIME_VERSION = getSystemProperty("java.runtime.version");
/**
- * The java.specification.name
System Property. Java Runtime Environment
- * specification name.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The java.specification.name
System Property. Java Runtime Environment specification name.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.2
*/
public static final String JAVA_SPECIFICATION_NAME = getSystemProperty("java.specification.name");
/**
- * The java.specification.vendor
System Property. Java Runtime Environment
- * specification vendor.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The java.specification.vendor
System Property. Java Runtime Environment specification vendor.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.2
*/
public static final String JAVA_SPECIFICATION_VENDOR = getSystemProperty("java.specification.vendor");
/**
- * The java.specification.version
System Property. Java Runtime Environment
- * specification version.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The java.specification.version
System Property. Java Runtime Environment specification version.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.3
*/
public static final String JAVA_SPECIFICATION_VERSION = getSystemProperty("java.specification.version");
/**
- * The java.vendor
System Property. Java vendor-specific string.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The java.util.prefs.PreferencesFactory
System Property. A class name.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
+ * @since 2.1
+ * @since Java 1.4
+ */
+ public static final String JAVA_UTIL_PREFS_PREFERENCES_FACTORY =
+ getSystemProperty("java.util.prefs.PreferencesFactory");
+
+ /**
+ *
+ * The java.vendor
System Property. Java vendor-specific string.
+ *
+ *
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.1
*/
public static final String JAVA_VENDOR = getSystemProperty("java.vendor");
/**
- * The java.vendor.url
System Property. Java vendor URL.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
- *
+ *
+ * The java.vendor.url
System Property. Java vendor URL.
+ *
+ *
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.1
- */
+ */
public static final String JAVA_VENDOR_URL = getSystemProperty("java.vendor.url");
/**
- * The java.version
System Property. Java version number.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The java.version
System Property. Java version number.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.1
*/
public static final String JAVA_VERSION = getSystemProperty("java.version");
/**
- * The java.vm.info
System Property. Java Virtual Machine implementation
- * info.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The java.vm.info
System Property. Java Virtual Machine implementation info.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since 2.0
* @since Java 1.2
*/
public static final String JAVA_VM_INFO = getSystemProperty("java.vm.info");
/**
- * The java.vm.name
System Property. Java Virtual Machine implementation
- * name.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The java.vm.name
System Property. Java Virtual Machine implementation name.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.2
*/
public static final String JAVA_VM_NAME = getSystemProperty("java.vm.name");
/**
- * The java.vm.specification.name
System Property. Java Virtual Machine
- * specification name.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The java.vm.specification.name
System Property. Java Virtual Machine specification name.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.2
*/
public static final String JAVA_VM_SPECIFICATION_NAME = getSystemProperty("java.vm.specification.name");
/**
- * The java.vm.specification.vendor
System Property. Java Virtual
- * Machine specification vendor.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The java.vm.specification.vendor
System Property. Java Virtual Machine specification vendor.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.2
*/
public static final String JAVA_VM_SPECIFICATION_VENDOR = getSystemProperty("java.vm.specification.vendor");
/**
- * The java.vm.specification.version
System Property. Java Virtual Machine
- * specification version.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The java.vm.specification.version
System Property. Java Virtual Machine specification version.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.2
*/
public static final String JAVA_VM_SPECIFICATION_VERSION = getSystemProperty("java.vm.specification.version");
/**
- * The java.vm.vendor
System Property. Java Virtual Machine implementation
- * vendor.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The java.vm.vendor
System Property. Java Virtual Machine implementation vendor.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.2
*/
public static final String JAVA_VM_VENDOR = getSystemProperty("java.vm.vendor");
/**
- * The java.vm.version
System Property. Java Virtual Machine
- * implementation version.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The java.vm.version
System Property. Java Virtual Machine implementation version.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.2
*/
public static final String JAVA_VM_VERSION = getSystemProperty("java.vm.version");
/**
- * The line.separator
System Property. Line separator
- * ("\n<"
on UNIX).
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The line.separator
System Property. Line separator ("\n"
on UNIX).
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.1
*/
public static final String LINE_SEPARATOR = getSystemProperty("line.separator");
/**
- * The os.arch
System Property. Operating system architecture.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The os.arch
System Property. Operating system architecture.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.1
*/
public static final String OS_ARCH = getSystemProperty("os.arch");
/**
- * The os.name
System Property. Operating system name.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The os.name
System Property. Operating system name.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.1
*/
public static final String OS_NAME = getSystemProperty("os.name");
/**
- * The os.version
System Property. Operating system version.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The os.version
System Property. Operating system version.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.1
*/
public static final String OS_VERSION = getSystemProperty("os.version");
/**
- * The path.separator
System Property. Path separator
- * (":"
on UNIX).
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The path.separator
System Property. Path separator (":"
on UNIX).
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.1
*/
public static final String PATH_SEPARATOR = getSystemProperty("path.separator");
/**
- * The user.country
or user.region
System Property.
- * User's country code, such as GB
. First in JDK version 1.2 as
- * user.region
. Renamed to user.country
in 1.4
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The user.country
or user.region
System Property.
+ * User's country code, such as GB
. First in
+ * Java version 1.2 as user.region
. Renamed to user.country
in 1.4
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since 2.0
* @since Java 1.2
*/
public static final String USER_COUNTRY =
- (getSystemProperty("user.country") == null ?
- getSystemProperty("user.region") : getSystemProperty("user.country"));
+ getSystemProperty("user.country") == null ?
+ getSystemProperty("user.region") : getSystemProperty("user.country");
/**
- * The user.dir
System Property. User's current working
- * directory.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The user.dir
System Property. User's current working directory.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.1
*/
- public static final String USER_DIR = getSystemProperty("user.dir");
+ public static final String USER_DIR = getSystemProperty(USER_DIR_KEY);
/**
- * The user.home
System Property. User's home directory.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The user.home
System Property. User's home directory.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.1
*/
- public static final String USER_HOME = getSystemProperty("user.home");
+ public static final String USER_HOME = getSystemProperty(USER_HOME_KEY);
/**
- * The user.language
System Property. User's language code,
- * such as 'en'.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The user.language
System Property. User's language code, such as "en"
.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since 2.0
* @since Java 1.2
*/
public static final String USER_LANGUAGE = getSystemProperty("user.language");
/**
- * The user.name
System Property. User's account name.
- *
- * Defaults to null
if the runtime does not have
- * security access to read this property or the property does not exist.
+ *
+ * The user.name
System Property. User's account name.
+ *
*
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
* @since Java 1.1
*/
public static final String USER_NAME = getSystemProperty("user.name");
+ /**
+ *
+ * The user.timezone
System Property. For example: "America/Los_Angeles"
.
+ *
+ *
+ *
+ * Defaults to null
if the runtime does not have
+ * security access to read this property or the property does not exist.
+ *
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value
+ * will be out of sync with that System property.
+ *
+ *
+ * @since 2.1
+ */
+ public static final String USER_TIMEZONE = getSystemProperty("user.timezone");
+
// Java version
- //-----------------------------------------------------------------------
- // These MUST be declared after those above as they depend on the
+ // -----------------------------------------------------------------------
+ // This MUST be declared after those above as it depends on the
// values being set up
-
+
/**
- * Gets the Java version as a float
.
- *
- * Example return values:
+ *
+ * Gets the Java version as a String
trimming leading letters.
+ *
+ *
+ *
+ * The field will return null
if {@link #JAVA_VERSION} is null
.
+ *
+ *
+ * @since 2.1
+ */
+ public static final String JAVA_VERSION_TRIMMED = getJavaVersionTrimmed();
+
+ // Java version values
+ // -----------------------------------------------------------------------
+ // These MUST be declared after the trim above as they depend on the
+ // value being set up
+
+ /**
+ *
+ * Gets the Java version as a float
.
+ *
+ *
+ *
+ * Example return values:
+ *
*
- * 1.2f
for JDK 1.2
- * 1.31f
for JDK 1.3.1
+ * 1.2f
for Java 1.2
+ * 1.31f
for Java 1.3.1
*
- *
- * The field will return zero if {@link #JAVA_VERSION} is null
.
*
+ *
+ * The field will return zero if {@link #JAVA_VERSION} is null
.
+ *
+ *
* @since 2.0
*/
public static final float JAVA_VERSION_FLOAT = getJavaVersionAsFloat();
/**
- * Gets the Java version as an int
.
- *
- * Example return values:
+ *
+ * Gets the Java version as an int
.
+ *
+ *
+ *
+ * Example return values:
+ *
*
- * 120
for JDK 1.2
- * 131
for JDK 1.3.1
+ * 120
for Java 1.2
+ * 131
for Java 1.3.1
*
- *
- * The field will return zero if {@link #JAVA_VERSION} is null
.
*
+ *
+ * The field will return zero if {@link #JAVA_VERSION} is null
.
+ *
+ *
* @since 2.0
*/
public static final int JAVA_VERSION_INT = getJavaVersionAsInt();
// Java version checks
- //-----------------------------------------------------------------------
+ // -----------------------------------------------------------------------
// These MUST be declared after those above as they depend on the
// values being set up
-
+
/**
- * Is true
if this is Java version 1.1 (also 1.1.x versions).
- *
- * The field will return false
if {@link #JAVA_VERSION} is
- * null
.
+ *
+ * Is true
if this is Java version 1.1 (also 1.1.x versions).
+ *
+ *
+ *
+ * The field will return false
if {@link #JAVA_VERSION} is null
.
+ *
*/
public static final boolean IS_JAVA_1_1 = getJavaVersionMatches("1.1");
/**
- * Is true
if this is Java version 1.2 (also 1.2.x versions).
- *
- * The field will return false
if {@link #JAVA_VERSION} is
- * null
.
+ *
+ * Is true
if this is Java version 1.2 (also 1.2.x versions).
+ *
+ *
+ *
+ * The field will return false
if {@link #JAVA_VERSION} is null
.
+ *
*/
public static final boolean IS_JAVA_1_2 = getJavaVersionMatches("1.2");
/**
- * Is true
if this is Java version 1.3 (also 1.3.x versions).
- *
- * The field will return false
if {@link #JAVA_VERSION} is
- * null
.
+ *
+ * Is true
if this is Java version 1.3 (also 1.3.x versions).
+ *
+ *
+ *
+ * The field will return false
if {@link #JAVA_VERSION} is null
.
+ *
*/
public static final boolean IS_JAVA_1_3 = getJavaVersionMatches("1.3");
/**
- * Is true
if this is Java version 1.4 (also 1.4.x versions).
- *
- * The field will false
false if {@link #JAVA_VERSION} is
- * null
.
+ *
+ * Is true
if this is Java version 1.4 (also 1.4.x versions).
+ *
+ *
+ *
+ * The field will return false
if {@link #JAVA_VERSION} is null
.
+ *
*/
public static final boolean IS_JAVA_1_4 = getJavaVersionMatches("1.4");
/**
- * Is true
if this is Java version 1.5 (also 1.5.x versions).
- *
- * The field will return false
if {@link #JAVA_VERSION} is
- * null
.
+ *
+ * Is true
if this is Java version 1.5 (also 1.5.x versions).
+ *
+ *
+ *
+ * The field will return false
if {@link #JAVA_VERSION} is null
.
+ *
*/
public static final boolean IS_JAVA_1_5 = getJavaVersionMatches("1.5");
+ /**
+ *
+ * Is true
if this is Java version 1.6 (also 1.6.x versions).
+ *
+ *
+ *
+ * The field will return false
if {@link #JAVA_VERSION} is null
.
+ *
+ */
+ public static final boolean IS_JAVA_1_6 = getJavaVersionMatches("1.6");
+
+ /**
+ *
+ * Is true
if this is Java version 1.7 (also 1.7.x versions).
+ *
+ *
+ *
+ * The field will return false
if {@link #JAVA_VERSION} is null
.
+ *
+ *
+ * @since 2.5
+ */
+ public static final boolean IS_JAVA_1_7 = getJavaVersionMatches("1.7");
+
// Operating system checks
- //-----------------------------------------------------------------------
+ // -----------------------------------------------------------------------
// These MUST be declared after those above as they depend on the
// values being set up
// OS names from http://www.vamphq.com/os.html
- // Selected ones included - please advise commons-dev@jakarta.apache.org
+ // Selected ones included - please advise dev@commons.apache.org
// if you want another added or a mistake corrected
/**
- * Is true
if this is AIX.
- *
- * The field will return false
if OS_NAME
is
- * null
.
+ *
+ * Is true
if this is AIX.
+ *
*
+ *
+ * The field will return false
if OS_NAME
is null
.
+ *
+ *
* @since 2.0
*/
- public static final boolean IS_OS_AIX = getOSMatches("AIX");
+ public static final boolean IS_OS_AIX = getOSMatchesName("AIX");
/**
- * Is true
if this is HP-UX.
- *
- * The field will return false
if OS_NAME
is
- * null
.
+ *
+ * Is true
if this is HP-UX.
+ *
*
+ *
+ * The field will return false
if OS_NAME
is null
.
+ *
+ *
* @since 2.0
*/
- public static final boolean IS_OS_HP_UX = getOSMatches("HP-UX");
+ public static final boolean IS_OS_HP_UX = getOSMatchesName("HP-UX");
/**
- * Is true
if this is Irix.
- *
- * The field will return false
if OS_NAME
is
- * null
.
+ *
+ * Is true
if this is Irix.
+ *
*
+ *
+ * The field will return false
if OS_NAME
is null
.
+ *
+ *
* @since 2.0
*/
- public static final boolean IS_OS_IRIX = getOSMatches("Irix");
+ public static final boolean IS_OS_IRIX = getOSMatchesName("Irix");
/**
- * Is true
if this is Linux.
- *
- * The field will return false
if OS_NAME
is
- * null
.
+ *
+ * Is true
if this is Linux.
+ *
*
+ *
+ * The field will return false
if OS_NAME
is null
.
+ *
+ *
* @since 2.0
*/
- public static final boolean IS_OS_LINUX = getOSMatches("Linux") || getOSMatches("LINUX");
+ public static final boolean IS_OS_LINUX = getOSMatchesName("Linux") || getOSMatchesName("LINUX");
/**
- * Is true
if this is Mac.
- *
- * The field will return false
if OS_NAME
is
- * null
.
+ *
+ * Is true
if this is Mac.
+ *
*
+ *
+ * The field will return false
if OS_NAME
is null
.
+ *
+ *
* @since 2.0
*/
- public static final boolean IS_OS_MAC = getOSMatches("Mac");
+ public static final boolean IS_OS_MAC = getOSMatchesName("Mac");
/**
- * Is true
if this is Mac.
- *
- * The field will return false
if OS_NAME
is
- * null
.
+ *
+ * Is true
if this is Mac.
+ *
*
+ *
+ * The field will return false
if OS_NAME
is null
.
+ *
+ *
* @since 2.0
*/
- public static final boolean IS_OS_MAC_OSX = getOSMatches("Mac OS X");
+ public static final boolean IS_OS_MAC_OSX = getOSMatchesName("Mac OS X");
/**
- * Is true
if this is OS/2.
- *
- * The field will return false
if OS_NAME
is
- * null
.
+ *
+ * Is true
if this is OS/2.
+ *
*
+ *
+ * The field will return false
if OS_NAME
is null
.
+ *
+ *
* @since 2.0
*/
- public static final boolean IS_OS_OS2 = getOSMatches("OS/2");
+ public static final boolean IS_OS_OS2 = getOSMatchesName("OS/2");
/**
- * Is true
if this is Solaris.
- *
- * The field will return false
if OS_NAME
is
- * null
.
+ *
+ * Is true
if this is Solaris.
+ *
*
+ *
+ * The field will return false
if OS_NAME
is null
.
+ *
+ *
* @since 2.0
*/
- public static final boolean IS_OS_SOLARIS = getOSMatches("Solaris");
+ public static final boolean IS_OS_SOLARIS = getOSMatchesName("Solaris");
/**
- * Is true
if this is SunOS.
- *
- * The field will return false
if OS_NAME
is
- * null
.
+ *
+ * Is true
if this is SunOS.
+ *
*
+ *
+ * The field will return false
if OS_NAME
is null
.
+ *
+ *
* @since 2.0
*/
- public static final boolean IS_OS_SUN_OS = getOSMatches("SunOS");
+ public static final boolean IS_OS_SUN_OS = getOSMatchesName("SunOS");
/**
- * Is true
if this is Windows.
- *
- * The field will return false
if OS_NAME
is
- * null
.
+ *
+ * Is true
if this is a UNIX like system,
+ * as in any of AIX, HP-UX, Irix, Linux, MacOSX, Solaris or SUN OS.
+ *
*
+ *
+ * The field will return false
if OS_NAME
is null
.
+ *
+ *
+ * @since 2.1
+ */
+ public static final boolean IS_OS_UNIX =
+ IS_OS_AIX || IS_OS_HP_UX || IS_OS_IRIX || IS_OS_LINUX ||
+ IS_OS_MAC_OSX || IS_OS_SOLARIS || IS_OS_SUN_OS;
+
+ /**
+ *
+ * Is true
if this is Windows.
+ *
+ *
+ *
+ * The field will return false
if OS_NAME
is null
.
+ *
+ *
* @since 2.0
*/
- public static final boolean IS_OS_WINDOWS = getOSMatches("Windows");
+ public static final boolean IS_OS_WINDOWS = getOSMatchesName(OS_NAME_WINDOWS_PREFIX);
/**
- * Is true
if this is Windows 2000.
- *
- * The field will return false
if OS_NAME
is
- * null
.
+ *
+ * Is true
if this is Windows 2000.
+ *
*
+ *
+ * The field will return false
if OS_NAME
is null
.
+ *
+ *
* @since 2.0
*/
- public static final boolean IS_OS_WINDOWS_2000 = getOSMatches("Windows", "5.0");
+ public static final boolean IS_OS_WINDOWS_2000 = getOSMatches(OS_NAME_WINDOWS_PREFIX, "5.0");
/**
- * Is true
if this is Windows 95.
- *
- * The field will return false
if OS_NAME
is
- * null
.
+ *
+ * Is true
if this is Windows 95.
+ *
*
+ *
+ * The field will return false
if OS_NAME
is null
.
+ *
+ *
* @since 2.0
*/
- public static final boolean IS_OS_WINDOWS_95 = getOSMatches("Windows 9", "4.0");
- // JDK 1.2 running on Windows98 returns 'Windows 95', hence the above
+ public static final boolean IS_OS_WINDOWS_95 = getOSMatches(OS_NAME_WINDOWS_PREFIX + " 9", "4.0");
+ // Java 1.2 running on Windows98 returns 'Windows 95', hence the above
/**
- * Is true
if this is Windows 98.
- *
- * The field will return false
if OS_NAME
is
- * null
.
+ *
+ * Is true
if this is Windows 98.
+ *
*
+ *
+ * The field will return false
if OS_NAME
is null
.
+ *
+ *
* @since 2.0
*/
- public static final boolean IS_OS_WINDOWS_98 = getOSMatches("Windows 9", "4.1");
- // JDK 1.2 running on Windows98 returns 'Windows 95', hence the above
+ public static final boolean IS_OS_WINDOWS_98 = getOSMatches(OS_NAME_WINDOWS_PREFIX + " 9", "4.1");
+ // Java 1.2 running on Windows98 returns 'Windows 95', hence the above
/**
- * Is true
if this is Windows ME.
- *
- * The field will return false
if OS_NAME
is
- * null
.
+ *
+ * Is true
if this is Windows ME.
+ *
*
+ *
+ * The field will return false
if OS_NAME
is null
.
+ *
+ *
* @since 2.0
*/
- public static final boolean IS_OS_WINDOWS_ME = getOSMatches("Windows", "4.9");
- // JDK 1.2 running on WindowsME may return 'Windows 95', hence the above
+ public static final boolean IS_OS_WINDOWS_ME = getOSMatches(OS_NAME_WINDOWS_PREFIX, "4.9");
+ // Java 1.2 running on WindowsME may return 'Windows 95', hence the above
/**
- * Is true
if this is Windows NT.
- *
- * The field will return false
if OS_NAME
is
- * null
.
+ *
+ * Is true
if this is Windows NT.
+ *
*
+ *
+ * The field will return false
if OS_NAME
is null
.
+ *
+ *
* @since 2.0
*/
- public static final boolean IS_OS_WINDOWS_NT = getOSMatches("Windows NT");
- // Windows 2000 returns 'Windows 2000' but may suffer from same JDK1.2 problem
+ public static final boolean IS_OS_WINDOWS_NT = getOSMatchesName(OS_NAME_WINDOWS_PREFIX + " NT");
+ // Windows 2000 returns 'Windows 2000' but may suffer from same Java1.2 problem
/**
- * Is true
if this is Windows XP.
- *
- * The field will return false
if OS_NAME
is
- * null
.
+ *
+ * Is true
if this is Windows XP.
+ *
*
+ *
+ * The field will return false
if OS_NAME
is null
.
+ *
+ *
* @since 2.0
*/
- public static final boolean IS_OS_WINDOWS_XP = getOSMatches("Windows", "5.1");
- // Windows XP returns 'Windows 2000' just for fun...
+ public static final boolean IS_OS_WINDOWS_XP = getOSMatches(OS_NAME_WINDOWS_PREFIX, "5.1");
- //-----------------------------------------------------------------------
+ // -----------------------------------------------------------------------
/**
- * SystemUtils instances should NOT be constructed in standard
- * programming. Instead, the class should be used as
- * SystemUtils.FILE_SEPARATOR
.
- *
- * This constructor is public to permit tools that require a JavaBean
- * instance to operate.
+ *
+ * Is true
if this is Windows Vista.
+ *
+ *
+ *
+ * The field will return false
if OS_NAME
is null
.
+ *
+ *
+ * @since 2.4
*/
- public SystemUtils() {
+ public static final boolean IS_OS_WINDOWS_VISTA = getOSMatches(OS_NAME_WINDOWS_PREFIX, "6.0");
+
+ /**
+ *
+ * Is true
if this is Windows 7.
+ *
+ *
+ *
+ * The field will return false
if OS_NAME
is null
.
+ *
+ *
+ * @since 2.5
+ */
+ public static final boolean IS_OS_WINDOWS_7 = getOSMatches(OS_NAME_WINDOWS_PREFIX, "6.1");
+
+ /**
+ *
+ * Gets the Java home directory as a File
.
+ *
+ *
+ * @return a directory
+ * @throws SecurityException if a security manager exists and its
+ * checkPropertyAccess
method doesn't allow access to the specified system property.
+ * @see System#getProperty(String)
+ * @since 2.1
+ */
+ public static File getJavaHome() {
+ return new File(System.getProperty(JAVA_HOME_KEY));
}
-
- //-----------------------------------------------------------------------
+
/**
+ *
+ * Gets the Java IO temporary directory as a File
.
+ *
+ *
+ * @return a directory
+ * @throws SecurityException if a security manager exists and its
+ * checkPropertyAccess
method doesn't allow access to the specified system
+ * property.
+ * @see System#getProperty(String)
+ * @since 2.1
+ */
+ public static File getJavaIoTmpDir() {
+ return new File(System.getProperty(JAVA_IO_TMPDIR_KEY));
+ }
+
+ /**
* Gets the Java version number as a float
.
*
* Example return values:
@@ -732,155 +1404,498 @@
}
/**
- * Gets the Java version number as a float
.
- *
- * Example return values:
+ *
+ * Gets the Java version number as a float
.
+ *
+ *
+ *
+ * Example return values:
+ *
*
- * 1.2f
for JDK 1.2
- * 1.31f
for JDK 1.3.1
+ * 1.2f
for Java 1.2
+ * 1.31f
for Java 1.3.1
+ * 1.6f
for Java 1.6.0_20
*
*
- * Patch releases are not reported.
- * Zero is returned if {@link #JAVA_VERSION} is null
.
+ *
+ * Patch releases are not reported.
+ *
*
- * @return the version, for example 1.31f for JDK 1.3.1
+ * @return the version, for example 1.31f for Java 1.3.1
*/
private static float getJavaVersionAsFloat() {
- if (JAVA_VERSION == null) {
- return 0f;
- }
- String str = JAVA_VERSION.substring(0, 3);
- if (JAVA_VERSION.length() >= 5) {
- str = str + JAVA_VERSION.substring(4, 5);
- }
- return Float.parseFloat(str);
+ return toVersionFloat(toJavaVersionIntArray(SystemUtils.JAVA_VERSION, JAVA_VERSION_TRIM_SIZE));
}
-
+
/**
- * Gets the Java version number as an int
.
- *
- * Example return values:
+ *
+ * Gets the Java version number as an int
.
+ *
+ *
+ *
+ * Example return values:
+ *
*
- * 120
for JDK 1.2
- * 131
for JDK 1.3.1
+ * 120
for Java 1.2
+ * 131
for Java 1.3.1
+ * 160
for Java 1.6.0_20
*
*
- * Patch releases are not reported.
- * Zero is returned if {@link #JAVA_VERSION} is null
.
+ *
+ * Patch releases are not reported.
+ *
*
- * @return the version, for example 131 for JDK 1.3.1
+ * @return the version, for example 131 for Java 1.3.1
*/
private static int getJavaVersionAsInt() {
- if (JAVA_VERSION == null) {
- return 0;
- }
- String str = JAVA_VERSION.substring(0, 1);
- str = str + JAVA_VERSION.substring(2, 3);
- if (JAVA_VERSION.length() >= 5) {
- str = str + JAVA_VERSION.substring(4, 5);
- } else {
- str = str + "0";
- }
- return Integer.parseInt(str);
+ return toVersionInt(toJavaVersionIntArray(SystemUtils.JAVA_VERSION, JAVA_VERSION_TRIM_SIZE));
}
/**
- * Decides if the java version matches.
+ *
+ * Decides if the Java version matches.
+ *
*
- * @param versionPrefix the prefix for the java version
+ * @param versionPrefix
+ * the prefix for the java version
* @return true if matches, or false if not or can't determine
*/
private static boolean getJavaVersionMatches(String versionPrefix) {
- if (JAVA_VERSION == null) {
- return false;
- }
- return JAVA_VERSION.startsWith(versionPrefix);
- }
-
+ return isJavaVersionMatch(JAVA_VERSION_TRIMMED, versionPrefix);
+ }
+
/**
- * Decides if the operating system matches.
+ * Trims the text of the java version to start with numbers.
*
- * @param osNamePrefix the prefix for the os name
- * @return true if matches, or false if not or can't determine
+ * @return the trimmed java version
*/
- private static boolean getOSMatches(String osNamePrefix) {
- if (OS_NAME == null) {
- return false;
+ private static String getJavaVersionTrimmed() {
+ if (JAVA_VERSION != null) {
+ for (int i = 0; i < JAVA_VERSION.length(); i++) {
+ char ch = JAVA_VERSION.charAt(i);
+ if (ch >= '0' && ch <= '9') {
+ return JAVA_VERSION.substring(i);
+ }
+ }
}
- return OS_NAME.startsWith(osNamePrefix);
- }
+ return null;
+ }
/**
- * Decides if the operating system matches.
+ * Decides if the operating system matches.
*
- * @param osNamePrefix the prefix for the os name
- * @param osVersionPrefix the prefix for the version
+ * @param osNamePrefix
+ * the prefix for the os name
+ * @param osVersionPrefix
+ * the prefix for the version
* @return true if matches, or false if not or can't determine
*/
private static boolean getOSMatches(String osNamePrefix, String osVersionPrefix) {
- if (OS_NAME == null || OS_VERSION == null) {
- return false;
- }
- return OS_NAME.startsWith(osNamePrefix) && OS_VERSION.startsWith(osVersionPrefix);
- }
+ return isOSMatch(OS_NAME, OS_VERSION, osNamePrefix, osVersionPrefix);
+ }
- //-----------------------------------------------------------------------
/**
- * Gets a System property, defaulting to null
if the property
- * cannot be read.
- *
- * If a SecurityException
is caught, the return
- * value is null
and a message is written to System.err
.
+ * Decides if the operating system matches.
*
- * @param property the system property name
+ * @param osNamePrefix
+ * the prefix for the os name
+ * @return true if matches, or false if not or can't determine
+ */
+ private static boolean getOSMatchesName(String osNamePrefix) {
+ return isOSNameMatch(OS_NAME, osNamePrefix);
+ }
+
+ // -----------------------------------------------------------------------
+ /**
+ *
+ * Gets a System property, defaulting to null
if the property cannot be read.
+ *
+ *
+ *
+ * If a SecurityException
is caught, the return value is null
and a message is written to
+ * System.err
.
+ *
+ *
+ * @param property
+ * the system property name
* @return the system property value or null
if a security problem occurs
*/
private static String getSystemProperty(String property) {
try {
return System.getProperty(property);
} catch (SecurityException ex) {
// we are not allowed to look at this property
- System.err.println(
- "Caught a SecurityException reading the system property '" + property
- + "'; the SystemUtils property value will default to null."
- );
+ System.err.println("Caught a SecurityException reading the system property '" + property
+ + "'; the SystemUtils property value will default to null.");
return null;
}
- }
-
+ }
+
/**
- * Is the Java version at least the requested version.
- *
- * Example input:
+ *
+ * Gets the user directory as a File
.
+ *
+ *
+ * @return a directory
+ * @throws SecurityException if a security manager exists and its
+ * checkPropertyAccess
method doesn't allow access to the specified system property.
+ * @see System#getProperty(String)
+ * @since 2.1
+ */
+ public static File getUserDir() {
+ return new File(System.getProperty(USER_DIR_KEY));
+ }
+
+ /**
+ *
+ * Gets the user home directory as a File
.
+ *
+ *
+ * @return a directory
+ * @throws SecurityException if a security manager exists and its
+ * checkPropertyAccess
method doesn't allow access to the specified system property.
+ * @see System#getProperty(String)
+ * @since 2.1
+ */
+ public static File getUserHome() {
+ return new File(System.getProperty(USER_HOME_KEY));
+ }
+
+ /**
+ * Returns whether the {@link #JAVA_AWT_HEADLESS} value is true
.
+ *
+ * @return true
if JAVA_AWT_HEADLESS
is "true"
, false
otherwise.
+ *
+ * @see #JAVA_AWT_HEADLESS
+ * @since 2.1
+ * @since Java 1.4
+ */
+ public static boolean isJavaAwtHeadless() {
+ return JAVA_AWT_HEADLESS != null ? JAVA_AWT_HEADLESS.equals(Boolean.TRUE.toString()) : false;
+ }
+
+ /**
+ *
+ * Is the Java version at least the requested version.
+ *
+ *
+ *
+ * Example input:
+ *
*
- * 1.2f
to test for JDK 1.2
- * 1.31f
to test for JDK 1.3.1
+ * 1.2f
to test for Java 1.2
+ * 1.31f
to test for Java 1.3.1
*
*
- * @param requiredVersion the required version, for example 1.31f
- * @return true
if the actual version is equal or greater
- * than the required version
+ * @param requiredVersion
+ * the required version, for example 1.31f
+ * @return true
if the actual version is equal or greater than the required version
*/
public static boolean isJavaVersionAtLeast(float requiredVersion) {
- return (JAVA_VERSION_FLOAT >= requiredVersion);
+ return JAVA_VERSION_FLOAT >= requiredVersion;
}
-
+
/**
- * Is the Java version at least the requested version.
- *
- * Example input:
+ *
+ * Is the Java version at least the requested version.
+ *
+ *
+ *
+ * Example input:
+ *
*
- * 120
to test for JDK 1.2 or greater
- * 131
to test for JDK 1.3.1 or greater
+ * 120
to test for Java 1.2 or greater
+ * 131
to test for Java 1.3.1 or greater
*
*
- * @param requiredVersion the required version, for example 131
- * @return true
if the actual version is equal or greater
- * than the required version
+ * @param requiredVersion
+ * the required version, for example 131
+ * @return true
if the actual version is equal or greater than the required version
* @since 2.0
*/
public static boolean isJavaVersionAtLeast(int requiredVersion) {
- return (JAVA_VERSION_INT >= requiredVersion);
+ return JAVA_VERSION_INT >= requiredVersion;
}
-
+
+ /**
+ *
+ * Decides if the Java version matches.
+ *
+ *
+ * This method is package private instead of private to support unit test invocation.
+ *
+ *
+ * @param version
+ * the actual Java version
+ * @param versionPrefix
+ * the prefix for the expected Java version
+ * @return true if matches, or false if not or can't determine
+ */
+ static boolean isJavaVersionMatch(String version, String versionPrefix) {
+ if (version == null) {
+ return false;
+ }
+ return version.startsWith(versionPrefix);
+ }
+
+ /**
+ * Decides if the operating system matches.
+ *
+ * This method is package private instead of private to support unit test invocation.
+ *
+ *
+ * @param osName
+ * the actual OS name
+ * @param osVersion
+ * the actual OS version
+ * @param osNamePrefix
+ * the prefix for the expected OS name
+ * @param osVersionPrefix
+ * the prefix for the expected OS version
+ * @return true if matches, or false if not or can't determine
+ */
+ static boolean isOSMatch(String osName, String osVersion, String osNamePrefix, String osVersionPrefix) {
+ if (osName == null || osVersion == null) {
+ return false;
+ }
+ return osName.startsWith(osNamePrefix) && osVersion.startsWith(osVersionPrefix);
+ }
+
+ /**
+ * Decides if the operating system matches.
+ *
+ * This method is package private instead of private to support unit test invocation.
+ *
+ *
+ * @param osName
+ * the actual OS name
+ * @param osNamePrefix
+ * the prefix for the expected OS name
+ * @return true if matches, or false if not or can't determine
+ */
+ static boolean isOSNameMatch(String osName, String osNamePrefix) {
+ if (osName == null) {
+ return false;
+ }
+ return osName.startsWith(osNamePrefix);
+ }
+
+ /**
+ *
+ * Converts the given Java version string to a float
.
+ *
+ *
+ *
+ * Example return values:
+ *
+ *
+ * 1.2f
for Java 1.2
+ * 1.31f
for Java 1.3.1
+ * 1.6f
for Java 1.6.0_20
+ *
+ *
+ *
+ * Patch releases are not reported.
+ *
+ *
+ * This method is package private instead of private to support unit test invocation.
+ *
+ *
+ * @param version The string version
+ * @return the version, for example 1.31f for Java 1.3.1
+ */
+ static float toJavaVersionFloat(String version) {
+ return toVersionFloat(toJavaVersionIntArray(version, JAVA_VERSION_TRIM_SIZE));
+ }
+
+ /**
+ *
+ * Converts the given Java version string to an int
.
+ *
+ *
+ *
+ * Example return values:
+ *
+ *
+ * 120
for Java 1.2
+ * 131
for Java 1.3.1
+ * 160
for Java 1.6.0_20
+ *
+ *
+ *
+ * Patch releases are not reported.
+ *
+ *
+ * This method is package private instead of private to support unit test invocation.
+ *
+ *
+ * @param version The string version
+ * @return the version, for example 131 for Java 1.3.1
+ */
+ static int toJavaVersionInt(String version) {
+ return toVersionInt(toJavaVersionIntArray(version, JAVA_VERSION_TRIM_SIZE));
+ }
+
+ /**
+ *
+ * Converts the given Java version string to an int[]
of maximum size 3
.
+ *
+ *
+ *
+ * Example return values:
+ *
+ *
+ * [1, 2, 0]
for Java 1.2
+ * [1, 3, 1]
for Java 1.3.1
+ * [1, 5, 0]
for Java 1.5.0_21
+ *
+ *
+ * This method is package private instead of private to support unit test invocation.
+ *
+ *
+ * @param version The string version
+ * @return the version, for example [1, 5, 0] for Java 1.5.0_21
+ */
+ static int[] toJavaVersionIntArray(String version) {
+ return toJavaVersionIntArray(version, Integer.MAX_VALUE);
+ }
+
+ /**
+ *
+ * Converts the given Java version string to an int[]
of maximum size limit
.
+ *
+ *
+ *
+ * Example return values:
+ *
+ *
+ * [1, 2, 0]
for Java 1.2
+ * [1, 3, 1]
for Java 1.3.1
+ * [1, 5, 0, 21]
for Java 1.5.0_21
+ *
+ *
+ * @param version The string version
+ * @param limit version limit
+ * @return the version, for example [1, 5, 0, 21] for Java 1.5.0_21
+ */
+ private static int[] toJavaVersionIntArray(String version, int limit) {
+ if (version == null) {
+ return ArrayUtils.EMPTY_INT_ARRAY;
+ }
+ String[] strings = StringUtils.split(version, "._- ");
+ int[] ints = new int[Math.min(limit, strings.length)];
+ int j = 0;
+ for (int i = 0; i < strings.length && j < limit; i++) {
+ String s = strings[i];
+ if (s.length() > 0) {
+ try {
+ ints[j] = Integer.parseInt(s);
+ j++;
+ } catch (Exception e) {
+ }
+ }
+ }
+ if (ints.length > j) {
+ int[] newInts = new int[j];
+ System.arraycopy(ints, 0, newInts, 0, j);
+ ints = newInts;
+ }
+ return ints;
+ }
+
+ /**
+ *
+ * Converts given the Java version array to a float
.
+ *
+ *
+ *
+ * Example return values:
+ *
+ *
+ * 1.2f
for Java 1.2
+ * 1.31f
for Java 1.3.1
+ * 1.6f
for Java 1.6.0_20
+ *
+ *
+ *
+ * Patch releases are not reported.
+ *
+ *
+ * @param javaVersions The version numbers
+ * @return the version, for example 1.31f for Java 1.3.1
+ */
+ private static float toVersionFloat(int[] javaVersions) {
+ if (javaVersions == null || javaVersions.length == 0) {
+ return 0f;
+ }
+ if (javaVersions.length == 1) {
+ return javaVersions[0];
+ }
+ StringBuffer builder = new StringBuffer();
+ builder.append(javaVersions[0]);
+ builder.append('.');
+ for (int i = 1; i < javaVersions.length; i++) {
+ builder.append(javaVersions[i]);
+ }
+ try {
+ return Float.parseFloat(builder.toString());
+ } catch (Exception ex) {
+ return 0f;
+ }
+ }
+
+ /**
+ *
+ * Converts given the Java version array to an int
.
+ *
+ *
+ *
+ * Example return values:
+ *
+ *
+ * 120
for Java 1.2
+ * 131
for Java 1.3.1
+ * 160
for Java 1.6.0_20
+ *
+ *
+ *
+ * Patch releases are not reported.
+ *
+ *
+ * @param javaVersions The version numbers
+ * @return the version, for example 1.31f for Java 1.3.1
+ */
+ private static int toVersionInt(int[] javaVersions) {
+ if (javaVersions == null) {
+ return 0;
+ }
+ int intVersion = 0;
+ int len = javaVersions.length;
+ if (len >= 1) {
+ intVersion = javaVersions[0] * 100;
+ }
+ if (len >= 2) {
+ intVersion += javaVersions[1] * 10;
+ }
+ if (len >= 3) {
+ intVersion += javaVersions[2];
+ }
+ return intVersion;
+ }
+
+ // -----------------------------------------------------------------------
+ /**
+ *
+ * SystemUtils instances should NOT be constructed in standard programming. Instead, the class should be used as
+ * SystemUtils.FILE_SEPARATOR
.
+ *
+ *
+ *
+ * This constructor is public to permit tools that require a JavaBean instance to operate.
+ *
+ */
+ public SystemUtils() {
+ super();
+ }
+
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/UnhandledException.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/UnhandledException.java (.../UnhandledException.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/UnhandledException.java (.../UnhandledException.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,87 +1,73 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang;
import org.apache.commons.lang.exception.NestableRuntimeException;
/**
- * Thrown when it is impossible or undesirable to consume
- * or throw a checked exception.
+ * Thrown when it is impossible or undesirable to consume or throw a checked exception.
+ * This exception supplements the standard exception classes by providing a more
+ * semantically rich description of the problem.
*
+ * UnhandledException
represents the case where a method has to deal
+ * with a checked exception but does not wish to.
+ * Instead, the checked exception is rethrown in this unchecked wrapper.
+ *
+ *
+ * public void foo() {
+ * try {
+ * // do something that throws IOException
+ * } catch (IOException ex) {
+ * // don't want to or can't throw IOException from foo()
+ * throw new UnhandledException(ex);
+ * }
+ * }
+ *
+ *
* @author Matthew Hawthorne
* @since 2.0
* @version $Id$
*/
public class UnhandledException extends NestableRuntimeException {
/**
- * Constructs the exception using a cause.
+ * Required for serialization support.
*
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = 1832101364842773720L;
+
+ /**
+ * Constructs the exception using a cause.
+ *
* @param cause the underlying cause
*/
- public UnhandledException(Throwable cause) {
- super(cause);
- }
+ public UnhandledException(Throwable cause) {
+ super(cause);
+ }
/**
* Constructs the exception using a message and cause.
- *
+ *
* @param message the message to use
* @param cause the underlying cause
*/
- public UnhandledException(String message, Throwable cause) {
- super(message, cause);
- }
+ public UnhandledException(String message, Throwable cause) {
+ super(message, cause);
+ }
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/Validate.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/Validate.java (.../Validate.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/Validate.java (.../Validate.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,55 +1,18 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang;
@@ -58,7 +21,7 @@
import java.util.Map;
/**
- * Assists in validating arguments.
+ * This class assists in validating arguments.
*
* The class is based along the lines of JUnit. If an argument value is
* deemed invalid, an IllegalArgumentException is thrown. For example:
@@ -68,42 +31,39 @@
* Validate.notNull( surname, "The surname must not be null");
*
*
+ * @author Apache Software Foundation
* @author Ola Berg
- * @author Stephen Colebourne
* @author Gary Gregory
+ * @author Norm Deane
* @since 2.0
* @version $Id$
*/
public class Validate {
+ // Validate has no dependencies on other classes in Commons Lang at present
/**
* Constructor. This class should not normally be instantiated.
*/
public Validate() {
+ super();
}
-
+
// isTrue
//---------------------------------------------------------------------------------
-
/**
- * Validate an argument, throwing IllegalArgumentException
- * if the test result is false
.
- *
- * This is used when validating according to an arbitrary boolean expression,
- * such as validating a primitive number or using your own custom validation
- * expression.
+ * Validate that the argument condition is true
; otherwise
+ * throwing an exception with the specified message. This method is useful when
+ * validating according to an arbitrary boolean expression, such as validating an
+ * object or using your own custom validation expression.
*
- *
- * Validate.isTrue( myObject.isOk(), "The object is not OK: ", myObject);
- *
+ * Validate.isTrue( myObject.isOk(), "The object is not OK: ", myObject);
*
- * For performance reasons, the object is passed as a separate parameter and
- * appended to the message string only in the case of an error.
+ * For performance reasons, the object value is passed as a separate parameter and
+ * appended to the exception message only in the case of an error.
*
- * @param expression a boolean expression
- * @param message the exception message you would like to see if the
- * expression is false
- * @param value the value to append to the message in case of error
+ * @param expression the boolean expression to check
+ * @param message the exception message if invalid
+ * @param value the value to append to the message when invalid
* @throws IllegalArgumentException if expression is false
*/
public static void isTrue(boolean expression, String message, Object value) {
@@ -113,23 +73,19 @@
}
/**
- * Validate an argument, throwing IllegalArgumentException
- * if the test result is false
.
- *
- * This is used when validating according to an arbitrary boolean expression,
- * such as validating a primitive number or using your own custom validation
- * expression.
+ * Validate that the argument condition is true
; otherwise
+ * throwing an exception with the specified message. This method is useful when
+ * validating according to an arbitrary boolean expression, such as validating a
+ * primitive number or using your own custom validation expression.
*
- *
- * Validate.isTrue( i > 0, "The value must be greater than zero: ", i);
- *
+ * Validate.isTrue(i > 0.0, "The value must be greater than zero: ", i);
*
- * For performance reasons, the object is passed as a separate parameter and
- * appended to the message string only in the case of an error.
+ * For performance reasons, the long value is passed as a separate parameter and
+ * appended to the exception message only in the case of an error.
*
- * @param expression a boolean expression
- * @param message the exception message you would like to see if the expression is false
- * @param value the value to append to the message in case of error
+ * @param expression the boolean expression to check
+ * @param message the exception message if invalid
+ * @param value the value to append to the message when invalid
* @throws IllegalArgumentException if expression is false
*/
public static void isTrue(boolean expression, String message, long value) {
@@ -139,24 +95,19 @@
}
/**
- * Validate an argument, throwing IllegalArgumentException
- * if the test result is false
.
- *
- * This is used when validating according to an arbitrary boolean expression,
- * such as validating a primitive number or using your own custom validation
- * expression.
+ * Validate that the argument condition is true
; otherwise
+ * throwing an exception with the specified message. This method is useful when
+ * validating according to an arbitrary boolean expression, such as validating a
+ * primitive number or using your own custom validation expression.
*
- *
- * Validate.isTrue( d > 0.0, "The value must be greater than zero: ", d);
- *
+ * Validate.isTrue(d > 0.0, "The value must be greater than zero: ", d);
*
- * For performance reasons, the object is passed as a separate parameter and
- * appended to the message string only in the case of an error.
+ * For performance reasons, the double value is passed as a separate parameter and
+ * appended to the exception message only in the case of an error.
*
- * @param expression a boolean expression
- * @param message the exception message you would like to see if the expression
- * is false
- * @param value the value to append to the message in case of error
+ * @param expression the boolean expression to check
+ * @param message the exception message if invalid
+ * @param value the value to append to the message when invalid
* @throws IllegalArgumentException if expression is false
*/
public static void isTrue(boolean expression, String message, double value) {
@@ -166,24 +117,18 @@
}
/**
- * Validate an argument, throwing IllegalArgumentException
- * if the test result is false
.
- *
- * This is used when validating according to an arbitrary boolean expression,
- * such as validating a primitive number or using your own custom validation
- * expression.
+ * Validate that the argument condition is true
; otherwise
+ * throwing an exception with the specified message. This method is useful when
+ * validating according to an arbitrary boolean expression, such as validating a
+ * primitive number or using your own custom validation expression.
*
*
* Validate.isTrue( (i > 0), "The value must be greater than zero");
* Validate.isTrue( myObject.isOk(), "The object is not OK");
*
*
- * For performance reasons, the message string should not involve a string append,
- * instead use the {@link #isTrue(boolean, String, Object)} method.
- *
- * @param expression a boolean expression
- * @param message the exception message you would like to see if the expression
- * is false
+ * @param expression the boolean expression to check
+ * @param message the exception message if invalid
* @throws IllegalArgumentException if expression is false
*/
public static void isTrue(boolean expression, String message) {
@@ -193,21 +138,19 @@
}
/**
- * Validate an argument, throwing IllegalArgumentException
- * if the test result is false
.
- *
- * This is used when validating according to an arbitrary boolean expression,
- * such as validating a primitive number or using your own custom validation
- * expression.
+ * Validate that the argument condition is true
; otherwise
+ * throwing an exception. This method is useful when validating according
+ * to an arbitrary boolean expression, such as validating a
+ * primitive number or using your own custom validation expression.
*
*
- * Validate.isTrue( i > 0 );
- * Validate.isTrue( myObject.isOk() );
- *
+ * Validate.isTrue(i > 0);
+ * Validate.isTrue(myObject.isOk());
*
- * The message in the exception is 'The validated expression is false'.
+ * The message of the exception is "The validated expression is
+ * false".
*
- * @param expression a boolean expression
+ * @param expression the boolean expression to check
* @throws IllegalArgumentException if expression is false
*/
public static void isTrue(boolean expression) {
@@ -220,56 +163,48 @@
//---------------------------------------------------------------------------------
/**
- * Validate an argument, throwing IllegalArgumentException
- * if the argument is null
.
+ * Validate that the specified argument is not null
;
+ * otherwise throwing an exception.
*
- *
- * Validate.notNull(myObject, "The object must not be null");
- *
+ * Validate.notNull(myObject);
+ *
+ * The message of the exception is "The validated object is
+ * null".
*
- * @param object the object to check is not null
- * @param message the exception message you would like to see
- * if the object is null
+ * @param object the object to check
* @throws IllegalArgumentException if the object is null
*/
- public static void notNull(Object object, String message) {
- if (object == null) {
- throw new IllegalArgumentException(message);
- }
+ public static void notNull(Object object) {
+ notNull(object, "The validated object is null");
}
/**
- * Validate an argument, throwing IllegalArgumentException
- * if the argument is null
.
+ * Validate that the specified argument is not null
;
+ * otherwise throwing an exception with the specified message.
*
- *
- * Validate.notNull(myObject);
- *
- *
- * The message in the exception is 'The validated object is null'.
+ * Validate.notNull(myObject, "The object must not be null");
*
- * @param object the object to check is not null
- * @throws IllegalArgumentException if the object is null
+ * @param object the object to check
+ * @param message the exception message if invalid
*/
- public static void notNull(Object object) {
+ public static void notNull(Object object, String message) {
if (object == null) {
- throw new IllegalArgumentException("The validated object is null");
+ throw new IllegalArgumentException(message);
}
}
// notEmpty array
//---------------------------------------------------------------------------------
/**
- * Validate an argument, throwing IllegalArgumentException
- * if the argument array is empty (null
or no elements).
+ * Validate that the specified argument array is neither null
+ * nor a length of zero (no elements); otherwise throwing an exception
+ * with the specified message.
*
- *
- * Validate.notEmpty(myArray, "The array must not be empty");
- *
+ * Validate.notEmpty(myArray, "The array must not be empty");
*
- * @param array the array to check is not empty
- * @param message the exception message you would like to see if the array is empty
+ * @param array the array to check
+ * @param message the exception message if invalid
* @throws IllegalArgumentException if the array is empty
*/
public static void notEmpty(Object[] array, String message) {
@@ -279,37 +214,33 @@
}
/**
- * Validate an argument, throwing IllegalArgumentException
- * if the argument array is empty (null
or no elements).
+ * Validate that the specified argument array is neither null
+ * nor a length of zero (no elements); otherwise throwing an exception.
*
- *
- * Validate.notEmpty(myArray);
- *
- *
- * The message in the exception is 'The validated array is empty'.
+ *
Validate.notEmpty(myArray);
*
- * @param array the array to check is not empty
+ * The message in the exception is "The validated array is
+ * empty".
+ *
+ * @param array the array to check
* @throws IllegalArgumentException if the array is empty
*/
public static void notEmpty(Object[] array) {
- if (array == null || array.length == 0) {
- throw new IllegalArgumentException("The validated array is empty");
- }
+ notEmpty(array, "The validated array is empty");
}
// notEmpty collection
//---------------------------------------------------------------------------------
/**
- *
Validate an argument, throwing IllegalArgumentException
- * if the argument Collection is empty (null
or no elements).
+ * Validate that the specified argument collection is neither null
+ * nor a size of zero (no elements); otherwise throwing an exception
+ * with the specified message.
*
- *
- * Validate.notEmpty(myCollection, "The collection must not be empty");
- *
+ * Validate.notEmpty(myCollection, "The collection must not be empty");
*
- * @param collection the collection to check is not empty
- * @param message the exception message you would like to see if the collection is empty
+ * @param collection the collection to check
+ * @param message the exception message if invalid
* @throws IllegalArgumentException if the collection is empty
*/
public static void notEmpty(Collection collection, String message) {
@@ -319,37 +250,33 @@
}
/**
- * Validate an argument, throwing IllegalArgumentException
- * if the argument Collection is empty (null
or no elements).
+ * Validate that the specified argument collection is neither null
+ * nor a size of zero (no elements); otherwise throwing an exception.
*
- *
- * Validate.notEmpty(myCollection);
- *
- *
- * The message in the exception is 'The validated collection is empty'.
+ * Validate.notEmpty(myCollection);
*
- * @param collection the collection to check is not empty
+ * The message in the exception is "The validated collection is
+ * empty".
+ *
+ * @param collection the collection to check
* @throws IllegalArgumentException if the collection is empty
*/
public static void notEmpty(Collection collection) {
- if (collection == null || collection.size() == 0) {
- throw new IllegalArgumentException("The validated collection is empty");
- }
+ notEmpty(collection, "The validated collection is empty");
}
// notEmpty map
//---------------------------------------------------------------------------------
/**
- * Validate an argument, throwing IllegalArgumentException
- * if the argument Map is empty (null
or no elements).
+ * Validate that the specified argument map is neither null
+ * nor a size of zero (no elements); otherwise throwing an exception
+ * with the specified message.
*
- *
- * Validate.notEmpty(myMap, "The collection must not be empty");
- *
+ * Validate.notEmpty(myMap, "The map must not be empty");
*
- * @param map the map to check is not empty
- * @param message the exception message you would like to see if the map is empty
+ * @param map the map to check
+ * @param message the exception message if invalid
* @throws IllegalArgumentException if the map is empty
*/
public static void notEmpty(Map map, String message) {
@@ -359,37 +286,34 @@
}
/**
- * Validate an argument, throwing IllegalArgumentException
- * if the argument Map is empty (null
or no elements).
+ * Validate that the specified argument map is neither null
+ * nor a size of zero (no elements); otherwise throwing an exception.
*
- *
- * Validate.notEmpty(myMap);
- *
- *
- * The message in the exception is 'The validated map is empty'.
+ * Validate.notEmpty(myMap);
*
- * @param map the map to check is not empty
+ * The message in the exception is "The validated map is
+ * empty".
+ *
+ * @param map the map to check
* @throws IllegalArgumentException if the map is empty
+ * @see #notEmpty(Map, String)
*/
public static void notEmpty(Map map) {
- if (map == null || map.size() == 0) {
- throw new IllegalArgumentException("The validated map is empty");
- }
+ notEmpty(map, "The validated map is empty");
}
// notEmpty string
//---------------------------------------------------------------------------------
/**
- * Validate an argument, throwing IllegalArgumentException
- * if the argument String is empty (null
or zero length).
+ * Validate that the specified argument string is
+ * neither null
nor a length of zero (no characters);
+ * otherwise throwing an exception with the specified message.
*
- *
- * Validate.notEmpty(myString, "The string must not be empty");
- *
+ * Validate.notEmpty(myString, "The string must not be empty");
*
- * @param string the string to check is not empty
- * @param message the exception message you would like to see if the string is empty
+ * @param string the string to check
+ * @param message the exception message if invalid
* @throws IllegalArgumentException if the string is empty
*/
public static void notEmpty(String string, String message) {
@@ -399,41 +323,39 @@
}
/**
- * Validate an argument, throwing IllegalArgumentException
- * if the argument String is empty (null
or zero length).
+ * Validate that the specified argument string is
+ * neither null
nor a length of zero (no characters);
+ * otherwise throwing an exception with the specified message.
*
- *
- * Validate.notEmpty(myString);
- *
- *
- * The message in the exception is 'The validated string is empty'.
+ * Validate.notEmpty(myString);
*
- * @param string the string to check is not empty
+ * The message in the exception is "The validated
+ * string is empty".
+ *
+ * @param string the string to check
* @throws IllegalArgumentException if the string is empty
*/
public static void notEmpty(String string) {
- if (string == null || string.length() == 0) {
- throw new IllegalArgumentException("The validated string is empty");
- }
+ notEmpty(string, "The validated string is empty");
}
// notNullElements array
//---------------------------------------------------------------------------------
/**
- * Validate an argument, throwing IllegalArgumentException
- * if the argument array has null
elements or is
- * null
.
+ * Validate that the specified argument array is neither
+ * null
nor contains any elements that are null
;
+ * otherwise throwing an exception with the specified message.
*
- *
- * Validate.notEmpty(myArray, "The array must not contain null elements");
- *
+ * Validate.noNullElements(myArray, "The array contain null at position %d");
*
- * @param array the array to check
- * @param message the exception message if the array has
- * null
elements
- * @throws IllegalArgumentException if the array has null
- * elements or is null
+ * If the array is null
, then the message in the exception
+ * is "The validated object is null".
+ *
+ * @param array the array to check
+ * @param message the exception message if the collection has null
elements
+ * @throws IllegalArgumentException if the array is null
or
+ * an element in the array is null
*/
public static void noNullElements(Object[] array, String message) {
Validate.notNull(array);
@@ -445,19 +367,22 @@
}
/**
- * Validate an argument, throwing IllegalArgumentException
- * if the argument array has null
elements or is
- * null
.
+ * Validate that the specified argument array is neither
+ * null
nor contains any elements that are null
;
+ * otherwise throwing an exception.
*
- *
- * Validate.notEmpty(myArray);
- *
- *
- * The message in the exception is 'The validated array contains null element at index: '.
+ * Validate.noNullElements(myArray);
*
- * @param array the array to check
- * @throws IllegalArgumentException if the array has null
- * elements or is null
+ * If the array is null
, then the message in the exception
+ * is "The validated object is null".
+ *
+ * If the array has a null
element, then the message in the
+ * exception is "The validated array contains null element at index:
+ * " followed by the index.
+ *
+ * @param array the array to check
+ * @throws IllegalArgumentException if the array is null
or
+ * an element in the array is null
*/
public static void noNullElements(Object[] array) {
Validate.notNull(array);
@@ -472,51 +397,108 @@
//---------------------------------------------------------------------------------
/**
- * Validate an argument, throwing IllegalArgumentException
- * if the argument collection has null
elements or is
- * null
.
+ * Validate that the specified argument collection is neither
+ * null
nor contains any elements that are null
;
+ * otherwise throwing an exception with the specified message.
*
- *
- * Validate.notEmpty(myCollection, "The collection must not contain null elements");
- *
+ * Validate.noNullElements(myCollection, "The collection contains null elements");
*
+ * If the collection is null
, then the message in the exception
+ * is "The validated object is null".
+ *
+ *
* @param collection the collection to check
- * @param message the exception message if the array has
- * null
elements
- * @throws IllegalArgumentException if the collection has
- * null
elements or is null
+ * @param message the exception message if the collection has
+ * @throws IllegalArgumentException if the collection is null
or
+ * an element in the collection is null
*/
public static void noNullElements(Collection collection, String message) {
Validate.notNull(collection);
+ for (Iterator it = collection.iterator(); it.hasNext();) {
+ if (it.next() == null) {
+ throw new IllegalArgumentException(message);
+ }
+ }
+ }
+
+ /**
+ * Validate that the specified argument collection is neither
+ * null
nor contains any elements that are null
;
+ * otherwise throwing an exception.
+ *
+ *
Validate.noNullElements(myCollection);
+ *
+ * If the collection is null
, then the message in the exception
+ * is "The validated object is null".
+ *
+ * If the collection has a null
element, then the message in the
+ * exception is "The validated collection contains null element at index:
+ * " followed by the index.
+ *
+ * @param collection the collection to check
+ * @throws IllegalArgumentException if the collection is null
or
+ * an element in the collection is null
+ */
+ public static void noNullElements(Collection collection) {
+ Validate.notNull(collection);
int i = 0;
for (Iterator it = collection.iterator(); it.hasNext(); i++) {
if (it.next() == null) {
- throw new IllegalArgumentException(message);
+ throw new IllegalArgumentException("The validated collection contains null element at index: " + i);
}
}
}
/**
* Validate an argument, throwing IllegalArgumentException
- * if the argument collection has null
elements or is
- * null
.
+ * if the argument collection is null
or has elements that
+ * are not of type clazz
or a subclass.
*
*
- * Validate.notEmpty(myCollection);
+ * Validate.allElementsOfType(collection, String.class, "Collection has invalid elements");
*
*
- * The message in the exception is 'The validated collection contains null element at index: '.
+ * @param collection the collection to check, not null
+ * @param clazz the Class
which the collection's elements are expected to be, not null
+ * @param message the exception message if the Collection
has elements not of type clazz
+ * @since 2.1
+ */
+ public static void allElementsOfType(Collection collection, Class clazz, String message) {
+ Validate.notNull(collection);
+ Validate.notNull(clazz);
+ for (Iterator it = collection.iterator(); it.hasNext(); ) {
+ if (clazz.isInstance(it.next()) == false) {
+ throw new IllegalArgumentException(message);
+ }
+ }
+ }
+
+ /**
+ *
+ * Validate an argument, throwing IllegalArgumentException
if the argument collection is
+ * null
or has elements that are not of type clazz
or a subclass.
+ *
*
- * @param collection the collection to check
- * @throws IllegalArgumentException if the collection has
- * null
elements or is null
+ *
+ * Validate.allElementsOfType(collection, String.class);
+ *
+ *
+ *
+ * The message in the exception is 'The validated collection contains an element not of type clazz at index: '.
+ *
+ *
+ * @param collection the collection to check, not null
+ * @param clazz the Class
which the collection's elements are expected to be, not null
+ * @since 2.1
*/
- public static void noNullElements(Collection collection) {
+ public static void allElementsOfType(Collection collection, Class clazz) {
Validate.notNull(collection);
+ Validate.notNull(clazz);
int i = 0;
for (Iterator it = collection.iterator(); it.hasNext(); i++) {
- if (it.next() == null) {
- throw new IllegalArgumentException("The validated collection contains null element at index: " + i);
+ if (clazz.isInstance(it.next()) == false) {
+ throw new IllegalArgumentException("The validated collection contains an element not of type "
+ + clazz.getName() + " at index: " + i);
}
}
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/WordUtils.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/WordUtils.java (.../WordUtils.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/WordUtils.java (.../WordUtils.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,55 +1,18 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang;
@@ -61,8 +24,7 @@
* Each method documents its behaviour in more detail.
*
* @author Apache Jakarta Velocity
- * @author Henri Yandell
- * @author Stephen Colebourne
+ * @author Apache Software Foundation
* @author Henning P. Schmiedehausen
* @author Gary Gregory
* @since 2.0
@@ -71,14 +33,15 @@
public class WordUtils {
/**
- * WordWrapUtils
instances should NOT be constructed in
+ *
WordUtils
instances should NOT be constructed in
* standard programming. Instead, the class should be used as
- * WordWrapUtils.wrap("foo bar", 20);
.
+ * WordUtils.wrap("foo bar", 20);
.
*
* This constructor is public to permit tools that require a JavaBean
* instance to operate.
*/
public WordUtils() {
+ super();
}
// Wrapping
@@ -152,7 +115,7 @@
// }
// }
//
-// return (stringBuffer.toString());
+// return stringBuffer.toString();
// }
// Wrapping
@@ -256,8 +219,9 @@
//-----------------------------------------------------------------------
/**
* Capitalizes all the whitespace separated words in a String.
- * Only the first letter of each word is changed. To change all letters to
- * the capitalized case, use {@link #capitalizeFully(String)}.
+ * Only the first letter of each word is changed. To convert the
+ * rest of each word to lowercase at the same time,
+ * use {@link #capitalizeFully(String)}.
*
* Whitespace is defined by {@link Character#isWhitespace(char)}.
* A null
input String returns null
.
@@ -276,67 +240,122 @@
* @see #capitalizeFully(String)
*/
public static String capitalize(String str) {
- int strLen;
- if (str == null || (strLen = str.length()) == 0) {
+ return capitalize(str, null);
+ }
+
+ /**
+ *
Capitalizes all the delimiter separated words in a String.
+ * Only the first letter of each word is changed. To convert the
+ * rest of each word to lowercase at the same time,
+ * use {@link #capitalizeFully(String, char[])}.
+ *
+ * The delimiters represent a set of characters understood to separate words.
+ * The first string character and the first non-delimiter character after a
+ * delimiter will be capitalized.
+ *
+ * A null
input String returns null
.
+ * Capitalization uses the unicode title case, normally equivalent to
+ * upper case.
+ *
+ *
+ * WordUtils.capitalize(null, *) = null
+ * WordUtils.capitalize("", *) = ""
+ * WordUtils.capitalize(*, new char[0]) = *
+ * WordUtils.capitalize("i am fine", null) = "I Am Fine"
+ * WordUtils.capitalize("i aM.fine", {'.'}) = "I aM.Fine"
+ *
+ *
+ * @param str the String to capitalize, may be null
+ * @param delimiters set of characters to determine capitalization, null means whitespace
+ * @return capitalized String, null
if null String input
+ * @see #uncapitalize(String)
+ * @see #capitalizeFully(String)
+ * @since 2.1
+ */
+ public static String capitalize(String str, char[] delimiters) {
+ int delimLen = (delimiters == null ? -1 : delimiters.length);
+ if (str == null || str.length() == 0 || delimLen == 0) {
return str;
}
+ int strLen = str.length();
StringBuffer buffer = new StringBuffer(strLen);
- boolean whitespace = true;
+ boolean capitalizeNext = true;
for (int i = 0; i < strLen; i++) {
char ch = str.charAt(i);
- if (Character.isWhitespace(ch)) {
+
+ if (isDelimiter(ch, delimiters)) {
buffer.append(ch);
- whitespace = true;
- } else if (whitespace) {
+ capitalizeNext = true;
+ } else if (capitalizeNext) {
buffer.append(Character.toTitleCase(ch));
- whitespace = false;
+ capitalizeNext = false;
} else {
buffer.append(ch);
}
}
return buffer.toString();
}
+ //-----------------------------------------------------------------------
/**
- * Capitalizes all the whitespace separated words in a String.
- * All letters are changed, so the resulting string will be fully changed.
+ * Converts all the whitespace separated words in a String into capitalized words,
+ * that is each word is made up of a titlecase character and then a series of
+ * lowercase characters.
*
* Whitespace is defined by {@link Character#isWhitespace(char)}.
* A null
input String returns null
.
* Capitalization uses the unicode title case, normally equivalent to
* upper case.
*
*
- * WordUtils.capitalize(null) = null
- * WordUtils.capitalize("") = ""
- * WordUtils.capitalize("i am FINE") = "I Am Fine"
+ * WordUtils.capitalizeFully(null) = null
+ * WordUtils.capitalizeFully("") = ""
+ * WordUtils.capitalizeFully("i am FINE") = "I Am Fine"
*
*
* @param str the String to capitalize, may be null
* @return capitalized String, null
if null String input
*/
public static String capitalizeFully(String str) {
- int strLen;
- if (str == null || (strLen = str.length()) == 0) {
+ return capitalizeFully(str, null);
+ }
+
+ /**
+ * Converts all the delimiter separated words in a String into capitalized words,
+ * that is each word is made up of a titlecase character and then a series of
+ * lowercase characters.
+ *
+ * The delimiters represent a set of characters understood to separate words.
+ * The first string character and the first non-delimiter character after a
+ * delimiter will be capitalized.
+ *
+ * A null
input String returns null
.
+ * Capitalization uses the unicode title case, normally equivalent to
+ * upper case.
+ *
+ *
+ * WordUtils.capitalizeFully(null, *) = null
+ * WordUtils.capitalizeFully("", *) = ""
+ * WordUtils.capitalizeFully(*, null) = *
+ * WordUtils.capitalizeFully(*, new char[0]) = *
+ * WordUtils.capitalizeFully("i aM.fine", {'.'}) = "I am.Fine"
+ *
+ *
+ * @param str the String to capitalize, may be null
+ * @param delimiters set of characters to determine capitalization, null means whitespace
+ * @return capitalized String, null
if null String input
+ * @since 2.1
+ */
+ public static String capitalizeFully(String str, char[] delimiters) {
+ int delimLen = (delimiters == null ? -1 : delimiters.length);
+ if (str == null || str.length() == 0 || delimLen == 0) {
return str;
}
- StringBuffer buffer = new StringBuffer(strLen);
- boolean whitespace = true;
- for (int i = 0; i < strLen; i++) {
- char ch = str.charAt(i);
- if (Character.isWhitespace(ch)) {
- buffer.append(ch);
- whitespace = true;
- } else if (whitespace) {
- buffer.append(Character.toTitleCase(ch));
- whitespace = false;
- } else {
- buffer.append(Character.toLowerCase(ch));
- }
- }
- return buffer.toString();
+ str = str.toLowerCase();
+ return capitalize(str, delimiters);
}
+ //-----------------------------------------------------------------------
/**
* Uncapitalizes all the whitespace separated words in a String.
* Only the first letter of each word is changed.
@@ -355,27 +374,59 @@
* @see #capitalize(String)
*/
public static String uncapitalize(String str) {
- int strLen;
- if (str == null || (strLen = str.length()) == 0) {
+ return uncapitalize(str, null);
+ }
+
+ /**
+ * Uncapitalizes all the whitespace separated words in a String.
+ * Only the first letter of each word is changed.
+ *
+ * The delimiters represent a set of characters understood to separate words.
+ * The first string character and the first non-delimiter character after a
+ * delimiter will be uncapitalized.
+ *
+ * Whitespace is defined by {@link Character#isWhitespace(char)}.
+ * A null
input String returns null
.
+ *
+ *
+ * WordUtils.uncapitalize(null, *) = null
+ * WordUtils.uncapitalize("", *) = ""
+ * WordUtils.uncapitalize(*, null) = *
+ * WordUtils.uncapitalize(*, new char[0]) = *
+ * WordUtils.uncapitalize("I AM.FINE", {'.'}) = "i AM.fINE"
+ *
+ *
+ * @param str the String to uncapitalize, may be null
+ * @param delimiters set of characters to determine uncapitalization, null means whitespace
+ * @return uncapitalized String, null
if null String input
+ * @see #capitalize(String)
+ * @since 2.1
+ */
+ public static String uncapitalize(String str, char[] delimiters) {
+ int delimLen = (delimiters == null ? -1 : delimiters.length);
+ if (str == null || str.length() == 0 || delimLen == 0) {
return str;
}
+ int strLen = str.length();
StringBuffer buffer = new StringBuffer(strLen);
- boolean whitespace = true;
+ boolean uncapitalizeNext = true;
for (int i = 0; i < strLen; i++) {
char ch = str.charAt(i);
- if (Character.isWhitespace(ch)) {
+
+ if (isDelimiter(ch, delimiters)) {
buffer.append(ch);
- whitespace = true;
- } else if (whitespace) {
+ uncapitalizeNext = true;
+ } else if (uncapitalizeNext) {
buffer.append(Character.toLowerCase(ch));
- whitespace = false;
+ uncapitalizeNext = false;
} else {
buffer.append(ch);
}
}
return buffer.toString();
}
+ //-----------------------------------------------------------------------
/**
* Swaps the case of a String using a word based algorithm.
*
@@ -429,5 +480,168 @@
}
return buffer.toString();
}
-
+
+ //-----------------------------------------------------------------------
+ /**
+ * Extracts the initial letters from each word in the String.
+ *
+ * The first letter of the string and all first letters after
+ * whitespace are returned as a new string.
+ * Their case is not changed.
+ *
+ * Whitespace is defined by {@link Character#isWhitespace(char)}.
+ * A null
input String returns null
.
+ *
+ *
+ * WordUtils.initials(null) = null
+ * WordUtils.initials("") = ""
+ * WordUtils.initials("Ben John Lee") = "BJL"
+ * WordUtils.initials("Ben J.Lee") = "BJ"
+ *
+ *
+ * @param str the String to get initials from, may be null
+ * @return String of initial letters, null
if null String input
+ * @see #initials(String,char[])
+ * @since 2.2
+ */
+ public static String initials(String str) {
+ return initials(str, null);
+ }
+
+ /**
+ * Extracts the initial letters from each word in the String.
+ *
+ * The first letter of the string and all first letters after the
+ * defined delimiters are returned as a new string.
+ * Their case is not changed.
+ *
+ * If the delimiters array is null, then Whitespace is used.
+ * Whitespace is defined by {@link Character#isWhitespace(char)}.
+ * A null
input String returns null
.
+ * An empty delimiter array returns an empty String.
+ *
+ *
+ * WordUtils.initials(null, *) = null
+ * WordUtils.initials("", *) = ""
+ * WordUtils.initials("Ben John Lee", null) = "BJL"
+ * WordUtils.initials("Ben J.Lee", null) = "BJ"
+ * WordUtils.initials("Ben J.Lee", [' ','.']) = "BJL"
+ * WordUtils.initials(*, new char[0]) = ""
+ *
+ *
+ * @param str the String to get initials from, may be null
+ * @param delimiters set of characters to determine words, null means whitespace
+ * @return String of initial letters, null
if null String input
+ * @see #initials(String)
+ * @since 2.2
+ */
+ public static String initials(String str, char[] delimiters) {
+ if (str == null || str.length() == 0) {
+ return str;
+ }
+ if (delimiters != null && delimiters.length == 0) {
+ return "";
+ }
+ int strLen = str.length();
+ char[] buf = new char[strLen / 2 + 1];
+ int count = 0;
+ boolean lastWasGap = true;
+ for (int i = 0; i < strLen; i++) {
+ char ch = str.charAt(i);
+
+ if (isDelimiter(ch, delimiters)) {
+ lastWasGap = true;
+ } else if (lastWasGap) {
+ buf[count++] = ch;
+ lastWasGap = false;
+ } else {
+ // ignore ch
+ }
+ }
+ return new String(buf, 0, count);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Is the character a delimiter.
+ *
+ * @param ch the character to check
+ * @param delimiters the delimiters
+ * @return true if it is a delimiter
+ */
+ private static boolean isDelimiter(char ch, char[] delimiters) {
+ if (delimiters == null) {
+ return Character.isWhitespace(ch);
+ }
+ for (int i = 0, isize = delimiters.length; i < isize; i++) {
+ if (ch == delimiters[i]) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Abbreviates a string nicely.
+ *
+ * This method searches for the first space after the lower limit and abbreviates
+ * the String there. It will also append any String passed as a parameter
+ * to the end of the String. The upper limit can be specified to forcibly
+ * abbreviate a String.
+ *
+ * @param str the string to be abbreviated. If null is passed, null is returned.
+ * If the empty String is passed, the empty string is returned.
+ * @param lower the lower limit.
+ * @param upper the upper limit; specify -1 if no limit is desired.
+ * If the upper limit is lower than the lower limit, it will be
+ * adjusted to be the same as the lower limit.
+ * @param appendToEnd String to be appended to the end of the abbreviated string.
+ * This is appended ONLY if the string was indeed abbreviated.
+ * The append does not count towards the lower or upper limits.
+ * @return the abbreviated String.
+ * @since 2.4
+ */
+ public static String abbreviate(String str, int lower, int upper, String appendToEnd) {
+ // initial parameter checks
+ if (str == null) {
+ return null;
+ }
+ if (str.length() == 0) {
+ return StringUtils.EMPTY;
+ }
+
+ // if the lower value is greater than the length of the string,
+ // set to the length of the string
+ if (lower > str.length()) {
+ lower = str.length();
+ }
+ // if the upper value is -1 (i.e. no limit) or is greater
+ // than the length of the string, set to the length of the string
+ if (upper == -1 || upper > str.length()) {
+ upper = str.length();
+ }
+ // if upper is less than lower, raise it to lower
+ if (upper < lower) {
+ upper = lower;
+ }
+
+ StringBuffer result = new StringBuffer();
+ int index = StringUtils.indexOf(str, " ", lower);
+ if (index == -1) {
+ result.append(str.substring(0, upper));
+ // only if abbreviation has occured do we append the appendToEnd value
+ if (upper != str.length()) {
+ result.append(StringUtils.defaultString(appendToEnd));
+ }
+ } else if (index > upper) {
+ result.append(str.substring(0, upper));
+ result.append(StringUtils.defaultString(appendToEnd));
+ } else {
+ result.append(str.substring(0, index));
+ result.append(StringUtils.defaultString(appendToEnd));
+ }
+ return result.toString();
+ }
+
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/CompareToBuilder.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/CompareToBuilder.java (.../CompareToBuilder.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/CompareToBuilder.java (.../CompareToBuilder.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,63 +1,28 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang.builder;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
+import java.util.Collection;
import java.util.Comparator;
+import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.math.NumberUtils;
/**
@@ -97,7 +62,7 @@
* }
*
*
- * Alternatively, there is a method {@link #reflectionCompare reflectionCompare} that uses
+ *
Alternatively, there are {@link #reflectionCompare(Object, Object) reflectionCompare} methods that use
* reflection to determine the fields to append. Because fields can be private,
* reflectionCompare
uses {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} to
* bypass normal access control checks. This will fail under a security manager,
@@ -118,8 +83,8 @@
* @see java.lang.Object#hashCode()
* @see EqualsBuilder
* @see HashCodeBuilder
+ * @author Apache Software Foundation
* @author Steve Downey
- * @author Stephen Colebourne
* @author Gary Gregory
* @author Pete Gieser
* @since 1.0
@@ -172,7 +137,7 @@
* with lhs
*/
public static int reflectionCompare(Object lhs, Object rhs) {
- return reflectionCompare(lhs, rhs, false, null);
+ return reflectionCompare(lhs, rhs, false, null, null);
}
/**
@@ -204,7 +169,7 @@
* with lhs
*/
public static int reflectionCompare(Object lhs, Object rhs, boolean compareTransients) {
- return reflectionCompare(lhs, rhs, compareTransients, null);
+ return reflectionCompare(lhs, rhs, compareTransients, null, null);
}
/**
@@ -216,6 +181,72 @@
*
*
* - Static fields will not be compared
+ * - If
compareTransients
is true
,
+ * compares transient members. Otherwise ignores them, as they
+ * are likely derived fields.
+ * - Superclass fields will be compared
+ *
+ *
+ * If both lhs
and rhs
are null
,
+ * they are considered equal.
+ *
+ * @param lhs left-hand object
+ * @param rhs right-hand object
+ * @param excludeFields Collection of String fields to exclude
+ * @return a negative integer, zero, or a positive integer as lhs
+ * is less than, equal to, or greater than rhs
+ * @throws NullPointerException if either lhs
or rhs
+ * (but not both) is null
+ * @throws ClassCastException if rhs
is not assignment-compatible
+ * with lhs
+ * @since 2.2
+ */
+ public static int reflectionCompare(Object lhs, Object rhs, Collection /*String*/ excludeFields) {
+ return reflectionCompare(lhs, rhs, ReflectionToStringBuilder.toNoNullStringArray(excludeFields));
+ }
+
+ /**
+ * Compares two Object
s via reflection.
+ *
+ * Fields can be private, thus AccessibleObject.setAccessible
+ * is used to bypass normal access control checks. This will fail under a
+ * security manager unless the appropriate permissions are set.
+ *
+ *
+ * - Static fields will not be compared
+ * - If
compareTransients
is true
,
+ * compares transient members. Otherwise ignores them, as they
+ * are likely derived fields.
+ * - Superclass fields will be compared
+ *
+ *
+ * If both lhs
and rhs
are null
,
+ * they are considered equal.
+ *
+ * @param lhs left-hand object
+ * @param rhs right-hand object
+ * @param excludeFields array of fields to exclude
+ * @return a negative integer, zero, or a positive integer as lhs
+ * is less than, equal to, or greater than rhs
+ * @throws NullPointerException if either lhs
or rhs
+ * (but not both) is null
+ * @throws ClassCastException if rhs
is not assignment-compatible
+ * with lhs
+ * @since 2.2
+ */
+ public static int reflectionCompare(Object lhs, Object rhs, String[] excludeFields) {
+ return reflectionCompare(lhs, rhs, false, null, excludeFields);
+ }
+
+ /**
+ * Compares two Object
s via reflection.
+ *
+ * Fields can be private, thus AccessibleObject.setAccessible
+ * is used to bypass normal access control checks. This will fail under a
+ * security manager unless the appropriate permissions are set.
+ *
+ *
+ * - Static fields will not be compared
* - If the
compareTransients
is true
,
* compares transient members. Otherwise ignores them, as they
* are likely derived fields.
@@ -238,7 +269,51 @@
* with lhs
* @since 2.0
*/
- public static int reflectionCompare(Object lhs, Object rhs, boolean compareTransients, Class reflectUpToClass) {
+ public static int reflectionCompare(Object lhs, Object rhs, boolean compareTransients,
+ Class reflectUpToClass)
+ {
+ return reflectionCompare(lhs, rhs, compareTransients, reflectUpToClass, null);
+ }
+
+ /**
+ * Compares two Object
s via reflection.
+ *
+ * Fields can be private, thus AccessibleObject.setAccessible
+ * is used to bypass normal access control checks. This will fail under a
+ * security manager unless the appropriate permissions are set.
+ *
+ *
+ * - Static fields will not be compared
+ * - If the
compareTransients
is true
,
+ * compares transient members. Otherwise ignores them, as they
+ * are likely derived fields.
+ * - Compares superclass fields up to and including
reflectUpToClass
.
+ * If reflectUpToClass
is null
, compares all superclass fields.
+ *
+ *
+ * If both lhs
and rhs
are null
,
+ * they are considered equal.
+ *
+ * @param lhs left-hand object
+ * @param rhs right-hand object
+ * @param compareTransients whether to compare transient fields
+ * @param reflectUpToClass last superclass for which fields are compared
+ * @param excludeFields fields to exclude
+ * @return a negative integer, zero, or a positive integer as lhs
+ * is less than, equal to, or greater than rhs
+ * @throws NullPointerException if either lhs
or rhs
+ * (but not both) is null
+ * @throws ClassCastException if rhs
is not assignment-compatible
+ * with lhs
+ * @since 2.2
+ */
+ public static int reflectionCompare(
+ Object lhs,
+ Object rhs,
+ boolean compareTransients,
+ Class reflectUpToClass,
+ String[] excludeFields) {
+
if (lhs == rhs) {
return 0;
}
@@ -250,10 +325,10 @@
throw new ClassCastException();
}
CompareToBuilder compareToBuilder = new CompareToBuilder();
- reflectionAppend(lhs, rhs, lhsClazz, compareToBuilder, compareTransients);
+ reflectionAppend(lhs, rhs, lhsClazz, compareToBuilder, compareTransients, excludeFields);
while (lhsClazz.getSuperclass() != null && lhsClazz != reflectUpToClass) {
lhsClazz = lhsClazz.getSuperclass();
- reflectionAppend(lhs, rhs, lhsClazz, compareToBuilder, compareTransients);
+ reflectionAppend(lhs, rhs, lhsClazz, compareToBuilder, compareTransients, excludeFields);
}
return compareToBuilder.toComparison();
}
@@ -267,19 +342,22 @@
* @param clazz Class
that defines fields to be compared
* @param builder CompareToBuilder
to append to
* @param useTransients whether to compare transient fields
+ * @param excludeFields fields to exclude
*/
private static void reflectionAppend(
Object lhs,
Object rhs,
Class clazz,
CompareToBuilder builder,
- boolean useTransients) {
+ boolean useTransients,
+ String[] excludeFields) {
Field[] fields = clazz.getDeclaredFields();
AccessibleObject.setAccessible(fields, true);
for (int i = 0; i < fields.length && builder.comparison == 0; i++) {
Field f = fields[i];
- if ((f.getName().indexOf('$') == -1)
+ if (!ArrayUtils.contains(excludeFields, f.getName())
+ && (f.getName().indexOf('$') == -1)
&& (useTransients || !Modifier.isTransient(f.getModifiers()))
&& (!Modifier.isStatic(f.getModifiers()))) {
try {
@@ -495,7 +573,7 @@
* Appends to the builder
the comparison of
* two double
s.
*
- * This handles NaNs, Infinties, and -0.0
.
+ * This handles NaNs, Infinities, and -0.0
.
*
* It is compatible with the hash code generated by
* HashCodeBuilder
.
@@ -516,7 +594,7 @@
* Appends to the builder
the comparison of
* two float
s.
*
- * This handles NaNs, Infinties, and -0.0
.
+ * This handles NaNs, Infinities, and -0.0
.
*
* It is compatible with the hash code generated by
* HashCodeBuilder
.
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/EqualsBuilder.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/EqualsBuilder.java (.../EqualsBuilder.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/EqualsBuilder.java (.../EqualsBuilder.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,62 +1,28 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang.builder;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
+import java.util.Collection;
+import org.apache.commons.lang.ArrayUtils;
+
/**
* Assists in implementing {@link Object#equals(Object)} methods.
*
@@ -78,13 +44,15 @@
*
* Typical use for the code is as follows:
*
- * public boolean equals(Object o) {
- * if ( !(o instanceof MyClass) ) {
- * return false;
+ * public boolean equals(Object obj) {
+ * if (obj == null) { return false; }
+ * if (obj == this) { return true; }
+ * if (obj.getClass() != getClass()) {
+ * return false;
* }
- * MyClass rhs = (MyClass) o;
- * return new EqualsBuilder()
- * .appendSuper(super.equals(o))
+ * MyClass rhs = (MyClass) obj;
+ * return new EqualsBuilder()
+ * .appendSuper(super.equals(obj))
* .append(field1, rhs.field1)
* .append(field2, rhs.field2)
* .append(field3, rhs.field3)
@@ -101,33 +69,35 @@
*
* A typical invocation for this method would look like:
*
- * public boolean equals(Object o) {
- * return EqualsBuilder.reflectionEquals(this, o);
+ * public boolean equals(Object obj) {
+ * return EqualsBuilder.reflectionEquals(this, obj);
* }
*
*
+ * @author Apache Software Foundation
* @author Steve Downey
- * @author Stephen Colebourne
* @author Gary Gregory
* @author Pete Gieser
+ * @author Arun Mammen Thomas
* @since 1.0
* @version $Id$
*/
public class EqualsBuilder {
+
/**
* If the fields tested are equals.
+ * The default value is true
.
*/
- private boolean isEquals;
+ private boolean isEquals = true;
/**
* Constructor for EqualsBuilder.
*
* Starts off assuming that equals is true
.
- * @see java.lang.Object#equals
+ * @see Object#equals(Object)
*/
public EqualsBuilder() {
- super();
- isEquals = true;
+ // do nothing for now.
}
//-------------------------------------------------------------------------
@@ -151,7 +121,7 @@
* @return true
if the two Objects have tested equals.
*/
public static boolean reflectionEquals(Object lhs, Object rhs) {
- return reflectionEquals(lhs, rhs, false, null);
+ return reflectionEquals(lhs, rhs, false, null, null);
}
/**
@@ -163,6 +133,52 @@
* a security manager, if the permissions are not set up correctly. It is also
* not as efficient as testing explicitly.
*
+ * Transient members will be not be tested, as they are likely derived
+ * fields, and not part of the value of the Object.
+ *
+ * Static fields will not be tested. Superclass fields will be included.
+ *
+ * @param lhs this
object
+ * @param rhs the other object
+ * @param excludeFields Collection of String field names to exclude from testing
+ * @return true
if the two Objects have tested equals.
+ */
+ public static boolean reflectionEquals(Object lhs, Object rhs, Collection /*String*/ excludeFields) {
+ return reflectionEquals(lhs, rhs, ReflectionToStringBuilder.toNoNullStringArray(excludeFields));
+ }
+
+ /**
+ * This method uses reflection to determine if the two Object
s
+ * are equal.
+ *
+ * It uses AccessibleObject.setAccessible
to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manager, if the permissions are not set up correctly. It is also
+ * not as efficient as testing explicitly.
+ *
+ * Transient members will be not be tested, as they are likely derived
+ * fields, and not part of the value of the Object.
+ *
+ * Static fields will not be tested. Superclass fields will be included.
+ *
+ * @param lhs this
object
+ * @param rhs the other object
+ * @param excludeFields array of field names to exclude from testing
+ * @return true
if the two Objects have tested equals.
+ */
+ public static boolean reflectionEquals(Object lhs, Object rhs, String[] excludeFields) {
+ return reflectionEquals(lhs, rhs, false, null, excludeFields);
+ }
+
+ /**
+ * This method uses reflection to determine if the two Object
s
+ * are equal.
+ *
+ * It uses AccessibleObject.setAccessible
to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manager, if the permissions are not set up correctly. It is also
+ * not as efficient as testing explicitly.
+ *
* If the TestTransients parameter is set to true
, transient
* members will be tested, otherwise they are ignored, as they are likely
* derived fields, and not part of the value of the Object
.
@@ -175,7 +191,7 @@
* @return true
if the two Objects have tested equals.
*/
public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients) {
- return reflectionEquals(lhs, rhs, testTransients, null);
+ return reflectionEquals(lhs, rhs, testTransients, null, null);
}
/**
@@ -204,6 +220,37 @@
* @since 2.0
*/
public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients, Class reflectUpToClass) {
+ return reflectionEquals(lhs, rhs, testTransients, reflectUpToClass, null);
+ }
+
+ /**
+ * This method uses reflection to determine if the two Object
s
+ * are equal.
+ *
+ * It uses AccessibleObject.setAccessible
to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manager, if the permissions are not set up correctly. It is also
+ * not as efficient as testing explicitly.
+ *
+ * If the testTransients parameter is set to true
, transient
+ * members will be tested, otherwise they are ignored, as they are likely
+ * derived fields, and not part of the value of the Object
.
+ *
+ * Static fields will not be included. Superclass fields will be appended
+ * up to and including the specified superclass. A null superclass is treated
+ * as java.lang.Object.
+ *
+ * @param lhs this
object
+ * @param rhs the other object
+ * @param testTransients whether to include transient fields
+ * @param reflectUpToClass the superclass to reflect up to (inclusive),
+ * may be null
+ * @param excludeFields array of field names to exclude from testing
+ * @return true
if the two Objects have tested equals.
+ * @since 2.0
+ */
+ public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients, Class reflectUpToClass,
+ String[] excludeFields) {
if (lhs == rhs) {
return true;
}
@@ -235,10 +282,10 @@
}
EqualsBuilder equalsBuilder = new EqualsBuilder();
try {
- reflectionAppend(lhs, rhs, testClass, equalsBuilder, testTransients);
+ reflectionAppend(lhs, rhs, testClass, equalsBuilder, testTransients, excludeFields);
while (testClass.getSuperclass() != null && testClass != reflectUpToClass) {
testClass = testClass.getSuperclass();
- reflectionAppend(lhs, rhs, testClass, equalsBuilder, testTransients);
+ reflectionAppend(lhs, rhs, testClass, equalsBuilder, testTransients, excludeFields);
}
} catch (IllegalArgumentException e) {
// In this case, we tried to test a subclass vs. a superclass and
@@ -260,18 +307,21 @@
* @param clazz the class to append details of
* @param builder the builder to append to
* @param useTransients whether to test transient fields
+ * @param excludeFields array of field names to exclude from testing
*/
private static void reflectionAppend(
Object lhs,
Object rhs,
Class clazz,
EqualsBuilder builder,
- boolean useTransients) {
+ boolean useTransients,
+ String[] excludeFields) {
Field[] fields = clazz.getDeclaredFields();
AccessibleObject.setAccessible(fields, true);
for (int i = 0; i < fields.length && builder.isEquals; i++) {
Field f = fields[i];
- if ((f.getName().indexOf('$') == -1)
+ if (!ArrayUtils.contains(excludeFields, f.getName())
+ && (f.getName().indexOf('$') == -1)
&& (useTransients || !Modifier.isTransient(f.getModifiers()))
&& (!Modifier.isStatic(f.getModifiers()))) {
try {
@@ -320,45 +370,51 @@
return this;
}
if (lhs == null || rhs == null) {
- isEquals = false;
+ this.setEquals(false);
return this;
}
Class lhsClass = lhs.getClass();
if (!lhsClass.isArray()) {
- //the simple case, not an array, just test the element
+ // The simple case, not an array, just test the element
isEquals = lhs.equals(rhs);
+ } else if (lhs.getClass() != rhs.getClass()) {
+ // Here when we compare different dimensions, for example: a boolean[][] to a boolean[]
+ this.setEquals(false);
+ }
+ // 'Switch' on type of array, to dispatch to the correct handler
+ // This handles multi dimensional arrays of the same depth
+ else if (lhs instanceof long[]) {
+ append((long[]) lhs, (long[]) rhs);
+ } else if (lhs instanceof int[]) {
+ append((int[]) lhs, (int[]) rhs);
+ } else if (lhs instanceof short[]) {
+ append((short[]) lhs, (short[]) rhs);
+ } else if (lhs instanceof char[]) {
+ append((char[]) lhs, (char[]) rhs);
+ } else if (lhs instanceof byte[]) {
+ append((byte[]) lhs, (byte[]) rhs);
+ } else if (lhs instanceof double[]) {
+ append((double[]) lhs, (double[]) rhs);
+ } else if (lhs instanceof float[]) {
+ append((float[]) lhs, (float[]) rhs);
+ } else if (lhs instanceof boolean[]) {
+ append((boolean[]) lhs, (boolean[]) rhs);
} else {
- //'Switch' on type of array, to dispatch to the correct handler
- // This handles multi dimensional arrays
- if (lhs instanceof long[]) {
- append((long[]) lhs, (long[]) rhs);
- } else if (lhs instanceof int[]) {
- append((int[]) lhs, (int[]) rhs);
- } else if (lhs instanceof short[]) {
- append((short[]) lhs, (short[]) rhs);
- } else if (lhs instanceof char[]) {
- append((char[]) lhs, (char[]) rhs);
- } else if (lhs instanceof byte[]) {
- append((byte[]) lhs, (byte[]) rhs);
- } else if (lhs instanceof double[]) {
- append((double[]) lhs, (double[]) rhs);
- } else if (lhs instanceof float[]) {
- append((float[]) lhs, (float[]) rhs);
- } else if (lhs instanceof boolean[]) {
- append((boolean[]) lhs, (boolean[]) rhs);
- } else {
- // Not an array of primitives
- append((Object[]) lhs, (Object[]) rhs);
- }
+ // Not an array of primitives
+ append((Object[]) lhs, (Object[]) rhs);
}
return this;
}
/**
- * Test if two long
s are equal.
- *
- * @param lhs the left hand long
- * @param rhs the right hand long
+ *
+ * Test if two long
s are equal.
+ *
+ *
+ * @param lhs
+ * the left hand long
+ * @param rhs
+ * the right hand long
* @return EqualsBuilder - used to chain calls.
*/
public EqualsBuilder append(long lhs, long rhs) {
@@ -433,7 +489,7 @@
* Test if two double
s are equal by testing that the
* pattern of bits returned by doubleToLong
are equal.
*
- * This handles NaNs, Infinties, and -0.0
.
+ * This handles NaNs, Infinities, and -0.0
.
*
* It is compatible with the hash code generated by
* HashCodeBuilder
.
@@ -453,7 +509,7 @@
* Test if two float
s are equal byt testing that the
* pattern of bits returned by doubleToLong are equal.
*
- * This handles NaNs, Infinties, and -0.0
.
+ * This handles NaNs, Infinities, and -0.0
.
*
* It is compatible with the hash code generated by
* HashCodeBuilder
.
@@ -502,19 +558,14 @@
return this;
}
if (lhs == null || rhs == null) {
- isEquals = false;
+ this.setEquals(false);
return this;
}
if (lhs.length != rhs.length) {
- isEquals = false;
+ this.setEquals(false);
return this;
}
for (int i = 0; i < lhs.length && isEquals; ++i) {
- Class lhsClass = lhs[i].getClass();
- if (!lhsClass.isInstance(rhs[i])) {
- isEquals = false; //If the types don't match, not equal
- break;
- }
append(lhs[i], rhs[i]);
}
return this;
@@ -538,11 +589,11 @@
return this;
}
if (lhs == null || rhs == null) {
- isEquals = false;
+ this.setEquals(false);
return this;
}
if (lhs.length != rhs.length) {
- isEquals = false;
+ this.setEquals(false);
return this;
}
for (int i = 0; i < lhs.length && isEquals; ++i) {
@@ -569,11 +620,11 @@
return this;
}
if (lhs == null || rhs == null) {
- isEquals = false;
+ this.setEquals(false);
return this;
}
if (lhs.length != rhs.length) {
- isEquals = false;
+ this.setEquals(false);
return this;
}
for (int i = 0; i < lhs.length && isEquals; ++i) {
@@ -600,11 +651,11 @@
return this;
}
if (lhs == null || rhs == null) {
- isEquals = false;
+ this.setEquals(false);
return this;
}
if (lhs.length != rhs.length) {
- isEquals = false;
+ this.setEquals(false);
return this;
}
for (int i = 0; i < lhs.length && isEquals; ++i) {
@@ -631,11 +682,11 @@
return this;
}
if (lhs == null || rhs == null) {
- isEquals = false;
+ this.setEquals(false);
return this;
}
if (lhs.length != rhs.length) {
- isEquals = false;
+ this.setEquals(false);
return this;
}
for (int i = 0; i < lhs.length && isEquals; ++i) {
@@ -662,11 +713,11 @@
return this;
}
if (lhs == null || rhs == null) {
- isEquals = false;
+ this.setEquals(false);
return this;
}
if (lhs.length != rhs.length) {
- isEquals = false;
+ this.setEquals(false);
return this;
}
for (int i = 0; i < lhs.length && isEquals; ++i) {
@@ -693,11 +744,11 @@
return this;
}
if (lhs == null || rhs == null) {
- isEquals = false;
+ this.setEquals(false);
return this;
}
if (lhs.length != rhs.length) {
- isEquals = false;
+ this.setEquals(false);
return this;
}
for (int i = 0; i < lhs.length && isEquals; ++i) {
@@ -724,11 +775,11 @@
return this;
}
if (lhs == null || rhs == null) {
- isEquals = false;
+ this.setEquals(false);
return this;
}
if (lhs.length != rhs.length) {
- isEquals = false;
+ this.setEquals(false);
return this;
}
for (int i = 0; i < lhs.length && isEquals; ++i) {
@@ -755,11 +806,11 @@
return this;
}
if (lhs == null || rhs == null) {
- isEquals = false;
+ this.setEquals(false);
return this;
}
if (lhs.length != rhs.length) {
- isEquals = false;
+ this.setEquals(false);
return this;
}
for (int i = 0; i < lhs.length && isEquals; ++i) {
@@ -769,13 +820,30 @@
}
/**
- * Return true
if the fields that have been checked
+ *
Returns true
if the fields that have been checked
* are all equal.
*
* @return boolean
*/
public boolean isEquals() {
- return isEquals;
+ return this.isEquals;
}
+ /**
+ * Sets the isEquals
value.
+ *
+ * @param isEquals The value to set.
+ * @since 2.1
+ */
+ protected void setEquals(boolean isEquals) {
+ this.isEquals = isEquals;
+ }
+
+ /**
+ * Reset the EqualsBuilder so you can use the same object again
+ * @since 2.5
+ */
+ public void reset() {
+ this.isEquals = true;
+ }
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/HashCodeBuilder.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/HashCodeBuilder.java (.../HashCodeBuilder.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/HashCodeBuilder.java (.../HashCodeBuilder.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,82 +1,64 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
+
package org.apache.commons.lang.builder;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import org.apache.commons.lang.ArrayUtils;
+
/**
- * Assists in implementing {@link Object#hashCode()} methods.
- *
- * This class enables a good hashCode
method to be built for any class. It
- * follows the rules laid out in the book
- * Effective Java
- * by Joshua Bloch. Writing a good hashCode
method is actually quite
- * difficult. This class aims to simplify the process.
- *
- * All relevant fields from the object should be included in the
- * hashCode
method. Derived fields may be excluded. In general, any
- * field used in the equals
method must be used in the hashCode
- * method.
- *
- * To use this class write code as follows:
+ *
+ * Assists in implementing {@link Object#hashCode()} methods.
+ *
+ *
+ *
+ * This class enables a good hashCode
method to be built for any class. It follows the rules laid out in
+ * the book Effective Java by Joshua Bloch. Writing a
+ * good hashCode
method is actually quite difficult. This class aims to simplify the process.
+ *
+ *
+ *
+ * The following is the approach taken. When appending a data field, the current total is multiplied by the
+ * multiplier then a relevant value
+ * for that data type is added. For example, if the current hashCode is 17, and the multiplier is 37, then
+ * appending the integer 45 will create a hashcode of 674, namely 17 * 37 + 45.
+ *
+ *
+ *
+ * All relevant fields from the object should be included in the hashCode
method. Derived fields may be
+ * excluded. In general, any field used in the equals
method must be used in the hashCode
+ * method.
+ *
+ *
+ *
+ * To use this class write code as follows:
+ *
+ *
*
* public class Person {
* String name;
* int age;
- * boolean isSmoker;
+ * boolean smoker;
* ...
*
* public int hashCode() {
@@ -90,429 +72,653 @@
* }
* }
*
- *
- * If required, the superclass hashCode()
can be added
- * using {@link #appendSuper}.
- *
- * Alternatively, there is a method that uses reflection to determine
- * the fields to test. Because these fields are usually private, the method,
- * reflectionHashCode
, uses AccessibleObject.setAccessible
to
- * change the visibility of the fields. This will fail under a security manager,
- * unless the appropriate permissions are set up correctly. It is also slower
- * than testing explicitly.
- *
- * A typical invocation for this method would look like:
+ *
+ *
+ * If required, the superclass hashCode()
can be added using {@link #appendSuper}.
+ *
+ *
+ *
+ * Alternatively, there is a method that uses reflection to determine the fields to test. Because these fields are
+ * usually private, the method, reflectionHashCode
, uses AccessibleObject.setAccessible
+ * to change the visibility of the fields. This will fail under a security manager, unless the appropriate permissions
+ * are set up correctly. It is also slower than testing explicitly.
+ *
+ *
+ *
+ * A typical invocation for this method would look like:
+ *
+ *
*
* public int hashCode() {
* return HashCodeBuilder.reflectionHashCode(this);
* }
*
- *
- * @author Stephen Colebourne
+ *
+ * @author Apache Software Foundation
* @author Gary Gregory
* @author Pete Gieser
* @since 1.0
* @version $Id$
*/
public class HashCodeBuilder {
-
/**
- * Constant to use in building the hashCode.
+ *
+ * A registry of objects used by reflection methods to detect cyclical object references and avoid infinite loops.
+ *
+ *
+ * @since 2.3
*/
- private final int iConstant;
+ private static final ThreadLocal REGISTRY = new ThreadLocal();
+
+ /*
+ * N.B. we cannot store the actual objects in a HashSet, as that would use the very hashCode()
+ * we are in the process of calculating.
+ *
+ * So we generate a one-to-one mapping from the original object to a new object.
+ *
+ * Now HashSet uses equals() to determine if two elements with the same hashcode really
+ * are equal, so we also need to ensure that the replacement objects are only equal
+ * if the original objects are identical.
+ *
+ * The original implementation (2.4 and before) used the System.indentityHashCode()
+ * method - however this is not guaranteed to generate unique ids (e.g. LANG-459)
+ *
+ * We now use the IDKey helper class (adapted from org.apache.axis.utils.IDKey)
+ * to disambiguate the duplicate ids.
+ */
+
/**
- * Running total of the hashCode.
+ *
+ * Returns the registry of objects being traversed by the reflection methods in the current thread.
+ *
+ *
+ * @return Set the registry of objects being traversed
+ * @since 2.3
*/
- private int iTotal = 0;
+ static Set getRegistry() {
+ return (Set) REGISTRY.get();
+ }
/**
- * Constructor.
- *
- * This constructor uses two hard coded choices for the constants
- * needed to build a hashCode
.
+ *
+ * Returns true
if the registry contains the given object. Used by the reflection methods to avoid
+ * infinite loops.
+ *
+ *
+ * @param value
+ * The object to lookup in the registry.
+ * @return boolean true
if the registry contains the given object.
+ * @since 2.3
*/
- public HashCodeBuilder() {
- super();
- iConstant = 37;
- iTotal = 17;
+ static boolean isRegistered(Object value) {
+ Set registry = getRegistry();
+ return registry != null && registry.contains(new IDKey(value));
}
/**
- * Constructor.
- *
- * Two randomly chosen, non-zero, odd numbers must be passed in.
- * Ideally these should be different for each class, however this is
- * not vital.
- *
- * Prime numbers are preferred, especially for the multiplier.
- *
- * @param initialNonZeroOddNumber a non-zero, odd number used as the initial value
- * @param multiplierNonZeroOddNumber a non-zero, odd number used as the multiplier
- * @throws IllegalArgumentException if the number is zero or even
+ *
+ * Appends the fields and values defined by the given object of the given Class
.
+ *
+ *
+ * @param object
+ * the object to append details of
+ * @param clazz
+ * the class to append details of
+ * @param builder
+ * the builder to append to
+ * @param useTransients
+ * whether to use transient fields
+ * @param excludeFields
+ * Collection of String field names to exclude from use in calculation of hash code
*/
- public HashCodeBuilder(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber) {
- super();
- if (initialNonZeroOddNumber == 0) {
- throw new IllegalArgumentException("HashCodeBuilder requires a non zero initial value");
+ private static void reflectionAppend(Object object, Class clazz, HashCodeBuilder builder, boolean useTransients,
+ String[] excludeFields) {
+ if (isRegistered(object)) {
+ return;
}
- if (initialNonZeroOddNumber % 2 == 0) {
- throw new IllegalArgumentException("HashCodeBuilder requires an odd initial value");
+ try {
+ register(object);
+ Field[] fields = clazz.getDeclaredFields();
+ AccessibleObject.setAccessible(fields, true);
+ for (int i = 0; i < fields.length; i++) {
+ Field field = fields[i];
+ if (!ArrayUtils.contains(excludeFields, field.getName())
+ && (field.getName().indexOf('$') == -1)
+ && (useTransients || !Modifier.isTransient(field.getModifiers()))
+ && (!Modifier.isStatic(field.getModifiers()))) {
+ try {
+ Object fieldValue = field.get(object);
+ builder.append(fieldValue);
+ } catch (IllegalAccessException e) {
+ // this can't happen. Would get a Security exception instead
+ // throw a runtime exception in case the impossible happens.
+ throw new InternalError("Unexpected IllegalAccessException");
+ }
+ }
+ }
+ } finally {
+ unregister(object);
}
- if (multiplierNonZeroOddNumber == 0) {
- throw new IllegalArgumentException("HashCodeBuilder requires a non zero multiplier");
- }
- if (multiplierNonZeroOddNumber % 2 == 0) {
- throw new IllegalArgumentException("HashCodeBuilder requires an odd multiplier");
- }
- iConstant = multiplierNonZeroOddNumber;
- iTotal = initialNonZeroOddNumber;
}
- //-------------------------------------------------------------------------
-
/**
- * This method uses reflection to build a valid hash code.
- *
- * This constructor uses two hard coded choices for the constants
- * needed to build a hash code.
- *
- * It uses AccessibleObject.setAccessible
to gain access to private
- * fields. This means that it will throw a security exception if run under
- * a security manager, if the permissions are not set up correctly. It is
- * also not as efficient as testing explicitly.
- *
- * Transient members will be not be used, as they are likely derived
- * fields, and not part of the value of the Object
.
- *
- * Static fields will not be tested. Superclass fields will be included.
- *
- * @param object the Object to create a hashCode
for
+ *
+ * This method uses reflection to build a valid hash code.
+ *
+ *
+ *
+ * It uses AccessibleObject.setAccessible
to gain access to private fields. This means that it will
+ * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
+ * also not as efficient as testing explicitly.
+ *
+ *
+ *
+ * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
+ * Object
.
+ *
+ *
+ *
+ * Static fields will not be tested. Superclass fields will be included.
+ *
+ *
+ *
+ * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
+ * however this is not vital. Prime numbers are preferred, especially for the multiplier.
+ *
+ *
+ * @param initialNonZeroOddNumber
+ * a non-zero, odd number used as the initial value
+ * @param multiplierNonZeroOddNumber
+ * a non-zero, odd number used as the multiplier
+ * @param object
+ * the Object to create a hashCode
for
* @return int hash code
- * @throws IllegalArgumentException if the object is null
+ * @throws IllegalArgumentException
+ * if the Object is null
+ * @throws IllegalArgumentException
+ * if the number is zero or even
*/
- public static int reflectionHashCode(Object object) {
- return reflectionHashCode(17, 37, object, false, null);
+ public static int reflectionHashCode(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object) {
+ return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, false, null, null);
}
/**
- * This method uses reflection to build a valid hash code.
- *
- * This constructor uses two hard coded choices for the constants needed
- * to build a hash code.
- *
- * It uses AccessibleObject.setAccessible
to gain access to private
- * fields. This means that it will throw a security exception if run under
- * a security manager, if the permissions are not set up correctly. It is
- * also not as efficient as testing explicitly.
- *
- * If the TestTransients parameter is set to true
, transient
- * members will be tested, otherwise they are ignored, as they are likely
- * derived fields, and not part of the value of the Object
.
- *
- * Static fields will not be tested. Superclass fields will be included.
- *
- * @param object the Object to create a hashCode
for
- * @param testTransients whether to include transient fields
+ *
+ * This method uses reflection to build a valid hash code.
+ *
+ *
+ *
+ * It uses AccessibleObject.setAccessible
to gain access to private fields. This means that it will
+ * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
+ * also not as efficient as testing explicitly.
+ *
+ *
+ *
+ * If the TestTransients parameter is set to true
, transient members will be tested, otherwise they
+ * are ignored, as they are likely derived fields, and not part of the value of the Object
.
+ *
+ *
+ *
+ * Static fields will not be tested. Superclass fields will be included.
+ *
+ *
+ *
+ * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
+ * however this is not vital. Prime numbers are preferred, especially for the multiplier.
+ *
+ *
+ * @param initialNonZeroOddNumber
+ * a non-zero, odd number used as the initial value
+ * @param multiplierNonZeroOddNumber
+ * a non-zero, odd number used as the multiplier
+ * @param object
+ * the Object to create a hashCode
for
+ * @param testTransients
+ * whether to include transient fields
* @return int hash code
- * @throws IllegalArgumentException if the object is null
+ * @throws IllegalArgumentException
+ * if the Object is null
+ * @throws IllegalArgumentException
+ * if the number is zero or even
*/
- public static int reflectionHashCode(Object object, boolean testTransients) {
- return reflectionHashCode(17, 37, object, testTransients, null);
+ public static int reflectionHashCode(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object,
+ boolean testTransients) {
+ return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, testTransients, null,
+ null);
}
/**
- * This method uses reflection to build a valid hash code.
- *
- * It uses AccessibleObject.setAccessible
to gain access to private
- * fields. This means that it will throw a security exception if run under
- * a security manager, if the permissions are not set up correctly. It is
- * also not as efficient as testing explicitly.
- *
- * Transient members will be not be used, as they are likely derived
- * fields, and not part of the value of the Object
.
- *
- * Static fields will not be tested. Superclass fields will be included.
- *
- * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
- * these should be different for each class, however this is not vital.
- * Prime numbers are preferred, especially for the multiplier.
- *
- * @param initialNonZeroOddNumber a non-zero, odd number used as the initial value
- * @param multiplierNonZeroOddNumber a non-zero, odd number used as the multiplier
- * @param object the Object to create a hashCode
for
+ * Calls {@link #reflectionHashCode(int, int, Object, boolean, Class, String[])} with excludeFields set to
+ * null
.
+ *
+ * @param initialNonZeroOddNumber
+ * a non-zero, odd number used as the initial value
+ * @param multiplierNonZeroOddNumber
+ * a non-zero, odd number used as the multiplier
+ * @param object
+ * the Object to create a hashCode
for
+ * @param testTransients
+ * whether to include transient fields
+ * @param reflectUpToClass
+ * the superclass to reflect up to (inclusive), may be null
* @return int hash code
- * @throws IllegalArgumentException if the Object is null
- * @throws IllegalArgumentException if the number is zero or even
*/
- public static int reflectionHashCode(
- int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object) {
- return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, false, null);
+ public static int reflectionHashCode(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object,
+ boolean testTransients, Class reflectUpToClass) {
+ return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, testTransients,
+ reflectUpToClass, null);
}
/**
- * This method uses reflection to build a valid hash code.
- *
- * It uses AccessibleObject.setAccessible
to gain access to private
- * fields. This means that it will throw a security exception if run under
- * a security manager, if the permissions are not set up correctly. It is also
- * not as efficient as testing explicitly.
- *
- * If the TestTransients parameter is set to true
, transient
- * members will be tested, otherwise they are ignored, as they are likely
- * derived fields, and not part of the value of the Object
.
- *
- * Static fields will not be tested. Superclass fields will be included.
- *
- * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
- * these should be different for each class, however this is not vital.
- * Prime numbers are preferred, especially for the multiplier.
- *
- * @param initialNonZeroOddNumber a non-zero, odd number used as the initial value
- * @param multiplierNonZeroOddNumber a non-zero, odd number used as the multiplier
- * @param object the Object to create a hashCode
for
- * @param testTransients whether to include transient fields
+ *
+ * This method uses reflection to build a valid hash code.
+ *
+ *
+ *
+ * It uses AccessibleObject.setAccessible
to gain access to private fields. This means that it will
+ * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
+ * also not as efficient as testing explicitly.
+ *
+ *
+ *
+ * If the TestTransients parameter is set to true
, transient members will be tested, otherwise they
+ * are ignored, as they are likely derived fields, and not part of the value of the Object
.
+ *
+ *
+ *
+ * Static fields will not be included. Superclass fields will be included up to and including the specified
+ * superclass. A null superclass is treated as java.lang.Object.
+ *
+ *
+ *
+ * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
+ * however this is not vital. Prime numbers are preferred, especially for the multiplier.
+ *
+ *
+ * @param initialNonZeroOddNumber
+ * a non-zero, odd number used as the initial value
+ * @param multiplierNonZeroOddNumber
+ * a non-zero, odd number used as the multiplier
+ * @param object
+ * the Object to create a hashCode
for
+ * @param testTransients
+ * whether to include transient fields
+ * @param reflectUpToClass
+ * the superclass to reflect up to (inclusive), may be null
+ * @param excludeFields
+ * array of field names to exclude from use in calculation of hash code
* @return int hash code
- * @throws IllegalArgumentException if the Object is null
- * @throws IllegalArgumentException if the number is zero or even
- */
- public static int reflectionHashCode(
- int initialNonZeroOddNumber, int multiplierNonZeroOddNumber,
- Object object, boolean testTransients) {
- return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, testTransients, null);
- }
-
- /**
- * This method uses reflection to build a valid hash code.
- *
- * It uses AccessibleObject.setAccessible
to gain access to private
- * fields. This means that it will throw a security exception if run under
- * a security manager, if the permissions are not set up correctly. It is also
- * not as efficient as testing explicitly.
- *
- * If the TestTransients parameter is set to true
, transient
- * members will be tested, otherwise they are ignored, as they are likely
- * derived fields, and not part of the value of the Object
.
- *
- * Static fields will not be included. Superclass fields will be included
- * up to and including the specified superclass. A null superclass is treated
- * as java.lang.Object.
- *
- * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
- * these should be different for each class, however this is not vital.
- * Prime numbers are preferred, especially for the multiplier.
- *
- * @param initialNonZeroOddNumber a non-zero, odd number used as the initial value
- * @param multiplierNonZeroOddNumber a non-zero, odd number used as the multiplier
- * @param object the Object to create a hashCode
for
- * @param testTransients whether to include transient fields
- * @param reflectUpToClass the superclass to reflect up to (inclusive),
- * may be null
- * @return int hash code
- * @throws IllegalArgumentException if the Object is null
- * @throws IllegalArgumentException if the number is zero or even
+ * @throws IllegalArgumentException
+ * if the Object is null
+ * @throws IllegalArgumentException
+ * if the number is zero or even
* @since 2.0
*/
- public static int reflectionHashCode(
- int initialNonZeroOddNumber,
- int multiplierNonZeroOddNumber,
- Object object,
- boolean testTransients,
- Class reflectUpToClass) {
+ public static int reflectionHashCode(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object,
+ boolean testTransients, Class reflectUpToClass, String[] excludeFields) {
if (object == null) {
throw new IllegalArgumentException("The object to build a hash code for must not be null");
}
HashCodeBuilder builder = new HashCodeBuilder(initialNonZeroOddNumber, multiplierNonZeroOddNumber);
Class clazz = object.getClass();
- reflectionAppend(object, clazz, builder, testTransients);
+ reflectionAppend(object, clazz, builder, testTransients, excludeFields);
while (clazz.getSuperclass() != null && clazz != reflectUpToClass) {
clazz = clazz.getSuperclass();
- reflectionAppend(object, clazz, builder, testTransients);
+ reflectionAppend(object, clazz, builder, testTransients, excludeFields);
}
return builder.toHashCode();
}
/**
- * Appends the fields and values defined by the given object of the
- * given Class
.
+ *
+ * This method uses reflection to build a valid hash code.
+ *
*
- * @param object the object to append details of
- * @param clazz the class to append details of
- * @param builder the builder to append to
- * @param useTransients whether to use transient fields
+ *
+ * This constructor uses two hard coded choices for the constants needed to build a hash code.
+ *
+ *
+ *
+ * It uses AccessibleObject.setAccessible
to gain access to private fields. This means that it will
+ * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
+ * also not as efficient as testing explicitly.
+ *
+ *
+ *
+ * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
+ * Object
.
+ *
+ *
+ *
+ * Static fields will not be tested. Superclass fields will be included.
+ *
+ *
+ * @param object
+ * the Object to create a hashCode
for
+ * @return int hash code
+ * @throws IllegalArgumentException
+ * if the object is null
*/
- private static void reflectionAppend(Object object, Class clazz, HashCodeBuilder builder, boolean useTransients) {
- Field[] fields = clazz.getDeclaredFields();
- AccessibleObject.setAccessible(fields, true);
- for (int i = 0; i < fields.length; i++) {
- Field f = fields[i];
- if ((f.getName().indexOf('$') == -1)
- && (useTransients || !Modifier.isTransient(f.getModifiers()))
- && (!Modifier.isStatic(f.getModifiers()))) {
- try {
- builder.append(f.get(object));
- } catch (IllegalAccessException e) {
- //this can't happen. Would get a Security exception instead
- //throw a runtime exception in case the impossible happens.
- throw new InternalError("Unexpected IllegalAccessException");
- }
- }
- }
+ public static int reflectionHashCode(Object object) {
+ return reflectionHashCode(17, 37, object, false, null, null);
}
- //-------------------------------------------------------------------------
+ /**
+ *
+ * This method uses reflection to build a valid hash code.
+ *
+ *
+ *
+ * This constructor uses two hard coded choices for the constants needed to build a hash code.
+ *
+ *
+ *
+ * It uses AccessibleObject.setAccessible
to gain access to private fields. This means that it will
+ * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
+ * also not as efficient as testing explicitly.
+ *
+ *
+ *
+ * If the TestTransients parameter is set to true
, transient members will be tested, otherwise they
+ * are ignored, as they are likely derived fields, and not part of the value of the Object
.
+ *
+ *
+ *
+ * Static fields will not be tested. Superclass fields will be included.
+ *
+ *
+ * @param object
+ * the Object to create a hashCode
for
+ * @param testTransients
+ * whether to include transient fields
+ * @return int hash code
+ * @throws IllegalArgumentException
+ * if the object is null
+ */
+ public static int reflectionHashCode(Object object, boolean testTransients) {
+ return reflectionHashCode(17, 37, object, testTransients, null, null);
+ }
/**
- * Adds the result of super.hashCode() to this builder.
- *
- * @param superHashCode the result of calling super.hashCode()
- * @return this HashCodeBuilder, used to chain calls.
- * @since 2.0
+ *
+ * This method uses reflection to build a valid hash code.
+ *
+ *
+ *
+ * This constructor uses two hard coded choices for the constants needed to build a hash code.
+ *
+ *
+ *
+ * It uses AccessibleObject.setAccessible
to gain access to private fields. This means that it will
+ * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
+ * also not as efficient as testing explicitly.
+ *
+ *
+ *
+ * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
+ * Object
.
+ *
+ *
+ *
+ * Static fields will not be tested. Superclass fields will be included.
+ *
+ *
+ * @param object
+ * the Object to create a hashCode
for
+ * @param excludeFields
+ * Collection of String field names to exclude from use in calculation of hash code
+ * @return int hash code
+ * @throws IllegalArgumentException
+ * if the object is null
*/
- public HashCodeBuilder appendSuper(int superHashCode) {
- iTotal = iTotal * iConstant + superHashCode;
- return this;
+ public static int reflectionHashCode(Object object, Collection /* String */excludeFields) {
+ return reflectionHashCode(object, ReflectionToStringBuilder.toNoNullStringArray(excludeFields));
}
- //-------------------------------------------------------------------------
+ // -------------------------------------------------------------------------
/**
- * Append a hashCode
for an Object
.
- *
- * @param object the Object to add to the hashCode
- * @return this
+ *
+ * This method uses reflection to build a valid hash code.
+ *
+ *
+ *
+ * This constructor uses two hard coded choices for the constants needed to build a hash code.
+ *
+ *
+ *
+ * It uses AccessibleObject.setAccessible
to gain access to private fields. This means that it will
+ * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
+ * also not as efficient as testing explicitly.
+ *
+ *
+ *
+ * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
+ * Object
.
+ *
+ *
+ *
+ * Static fields will not be tested. Superclass fields will be included.
+ *
+ *
+ * @param object
+ * the Object to create a hashCode
for
+ * @param excludeFields
+ * array of field names to exclude from use in calculation of hash code
+ * @return int hash code
+ * @throws IllegalArgumentException
+ * if the object is null
*/
- public HashCodeBuilder append(Object object) {
- if (object == null) {
- iTotal = iTotal * iConstant;
+ public static int reflectionHashCode(Object object, String[] excludeFields) {
+ return reflectionHashCode(17, 37, object, false, null, excludeFields);
+ }
- } else {
- if (object.getClass().isArray() == false) {
- //the simple case, not an array, just the element
- iTotal = iTotal * iConstant + object.hashCode();
+ /**
+ *
+ * Registers the given object. Used by the reflection methods to avoid infinite loops.
+ *
+ *
+ * @param value
+ * The object to register.
+ */
+ static void register(Object value) {
+ synchronized (HashCodeBuilder.class) {
+ if (getRegistry() == null) {
+ REGISTRY.set(new HashSet());
+ }
+ }
+ getRegistry().add(new IDKey(value));
+ }
- } else {
- //'Switch' on type of array, to dispatch to the correct handler
- // This handles multi dimensional arrays
- if (object instanceof long[]) {
- append((long[]) object);
- } else if (object instanceof int[]) {
- append((int[]) object);
- } else if (object instanceof short[]) {
- append((short[]) object);
- } else if (object instanceof char[]) {
- append((char[]) object);
- } else if (object instanceof byte[]) {
- append((byte[]) object);
- } else if (object instanceof double[]) {
- append((double[]) object);
- } else if (object instanceof float[]) {
- append((float[]) object);
- } else if (object instanceof boolean[]) {
- append((boolean[]) object);
- } else {
- // Not an array of primitives
- append((Object[]) object);
+ /**
+ *
+ * Unregisters the given object.
+ *
+ *
+ *
+ * Used by the reflection methods to avoid infinite loops.
+ *
+ * @param value
+ * The object to unregister.
+ * @since 2.3
+ */
+ static void unregister(Object value) {
+ Set registry = getRegistry();
+ if (registry != null) {
+ registry.remove(new IDKey(value));
+ synchronized (HashCodeBuilder.class) {
+ //read again
+ registry = getRegistry();
+ if (registry != null && registry.isEmpty()) {
+ REGISTRY.set(null);
}
}
}
- return this;
}
/**
- *
Append a hashCode
for a long
.
- *
- * @param value the long to add to the hashCode
- * @return this
+ * Constant to use in building the hashCode.
*/
- public HashCodeBuilder append(long value) {
- iTotal = iTotal * iConstant + ((int) (value ^ (value >> 32)));
- return this;
+ private final int iConstant;
+
+ /**
+ * Running total of the hashCode.
+ */
+ private int iTotal = 0;
+
+ /**
+ *
+ * Uses two hard coded choices for the constants needed to build a hashCode
.
+ *
+ */
+ public HashCodeBuilder() {
+ iConstant = 37;
+ iTotal = 17;
}
/**
- * Append a hashCode
for an int
.
- *
- * @param value the int to add to the hashCode
- * @return this
+ *
+ * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
+ * however this is not vital.
+ *
+ *
+ *
+ * Prime numbers are preferred, especially for the multiplier.
+ *
+ *
+ * @param initialNonZeroOddNumber
+ * a non-zero, odd number used as the initial value
+ * @param multiplierNonZeroOddNumber
+ * a non-zero, odd number used as the multiplier
+ * @throws IllegalArgumentException
+ * if the number is zero or even
*/
- public HashCodeBuilder append(int value) {
- iTotal = iTotal * iConstant + value;
- return this;
+ public HashCodeBuilder(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber) {
+ if (initialNonZeroOddNumber == 0) {
+ throw new IllegalArgumentException("HashCodeBuilder requires a non zero initial value");
+ }
+ if (initialNonZeroOddNumber % 2 == 0) {
+ throw new IllegalArgumentException("HashCodeBuilder requires an odd initial value");
+ }
+ if (multiplierNonZeroOddNumber == 0) {
+ throw new IllegalArgumentException("HashCodeBuilder requires a non zero multiplier");
+ }
+ if (multiplierNonZeroOddNumber % 2 == 0) {
+ throw new IllegalArgumentException("HashCodeBuilder requires an odd multiplier");
+ }
+ iConstant = multiplierNonZeroOddNumber;
+ iTotal = initialNonZeroOddNumber;
}
/**
- * Append a hashCode
for a short
.
- *
- * @param value the short to add to the hashCode
+ *
+ * Append a hashCode
for a boolean
.
+ *
+ *
+ * This adds 1
when true, and 0
when false to the hashCode
.
+ *
+ *
+ * This is in contrast to the standard java.lang.Boolean.hashCode
handling, which computes
+ * a hashCode
value of 1231
for java.lang.Boolean
instances
+ * that represent true
or 1237
for java.lang.Boolean
instances
+ * that represent false
.
+ *
+ *
+ * This is in accordance with the Effective Java
design.
+ *
+ *
+ * @param value
+ * the boolean to add to the hashCode
* @return this
*/
- public HashCodeBuilder append(short value) {
- iTotal = iTotal * iConstant + value;
+ public HashCodeBuilder append(boolean value) {
+ iTotal = iTotal * iConstant + (value ? 0 : 1);
return this;
}
/**
- * Append a hashCode
for a char
.
- *
- * @param value the char to add to the hashCode
+ *
+ * Append a hashCode
for a boolean
array.
+ *
+ *
+ * @param array
+ * the array to add to the hashCode
* @return this
*/
- public HashCodeBuilder append(char value) {
- iTotal = iTotal * iConstant + value;
+ public HashCodeBuilder append(boolean[] array) {
+ if (array == null) {
+ iTotal = iTotal * iConstant;
+ } else {
+ for (int i = 0; i < array.length; i++) {
+ append(array[i]);
+ }
+ }
return this;
}
+ // -------------------------------------------------------------------------
+
/**
- * Append a hashCode
for a byte
.
- *
- * @param value the byte to add to the hashCode
+ *
+ * Append a hashCode
for a byte
.
+ *
+ *
+ * @param value
+ * the byte to add to the hashCode
* @return this
*/
public HashCodeBuilder append(byte value) {
iTotal = iTotal * iConstant + value;
return this;
}
- /**
- * Append a hashCode
for a double
.
- *
- * @param value the double to add to the hashCode
- * @return this
- */
- public HashCodeBuilder append(double value) {
- return append(Double.doubleToLongBits(value));
- }
+ // -------------------------------------------------------------------------
/**
- * Append a hashCode
for a float
.
- *
- * @param value the float to add to the hashCode
+ *
+ * Append a hashCode
for a byte
array.
+ *
+ *
+ * @param array
+ * the array to add to the hashCode
* @return this
*/
- public HashCodeBuilder append(float value) {
- iTotal = iTotal * iConstant + Float.floatToIntBits(value);
+ public HashCodeBuilder append(byte[] array) {
+ if (array == null) {
+ iTotal = iTotal * iConstant;
+ } else {
+ for (int i = 0; i < array.length; i++) {
+ append(array[i]);
+ }
+ }
return this;
}
/**
- * Append a hashCode
for a boolean
.
- *
- * @param value the boolean to add to the hashCode
+ *
+ * Append a hashCode
for a char
.
+ *
+ *
+ * @param value
+ * the char to add to the hashCode
* @return this
*/
- public HashCodeBuilder append(boolean value) {
- iTotal = iTotal * iConstant + (value ? 0 : 1);
+ public HashCodeBuilder append(char value) {
+ iTotal = iTotal * iConstant + value;
return this;
}
/**
- * Append a hashCode
for an Object
array.
- *
- * @param array the array to add to the hashCode
+ *
+ * Append a hashCode
for a char
array.
+ *
+ *
+ * @param array
+ * the array to add to the hashCode
* @return this
*/
- public HashCodeBuilder append(Object[] array) {
+ public HashCodeBuilder append(char[] array) {
if (array == null) {
iTotal = iTotal * iConstant;
} else {
@@ -524,12 +730,28 @@
}
/**
- * Append a hashCode
for a long
array.
- *
- * @param array the array to add to the hashCode
+ *
+ * Append a hashCode
for a double
.
+ *
+ *
+ * @param value
+ * the double to add to the hashCode
* @return this
*/
- public HashCodeBuilder append(long[] array) {
+ public HashCodeBuilder append(double value) {
+ return append(Double.doubleToLongBits(value));
+ }
+
+ /**
+ *
+ * Append a hashCode
for a double
array.
+ *
+ *
+ * @param array
+ * the array to add to the hashCode
+ * @return this
+ */
+ public HashCodeBuilder append(double[] array) {
if (array == null) {
iTotal = iTotal * iConstant;
} else {
@@ -541,29 +763,29 @@
}
/**
- * Append a hashCode
for an int
array.
- *
- * @param array the array to add to the hashCode
+ *
+ * Append a hashCode
for a float
.
+ *
+ *
+ * @param value
+ * the float to add to the hashCode
* @return this
*/
- public HashCodeBuilder append(int[] array) {
- if (array == null) {
- iTotal = iTotal * iConstant;
- } else {
- for (int i = 0; i < array.length; i++) {
- append(array[i]);
- }
- }
+ public HashCodeBuilder append(float value) {
+ iTotal = iTotal * iConstant + Float.floatToIntBits(value);
return this;
}
/**
- * Append a hashCode
for a short
array.
- *
- * @param array the array to add to the hashCode
+ *
+ * Append a hashCode
for a float
array.
+ *
+ *
+ * @param array
+ * the array to add to the hashCode
* @return this
*/
- public HashCodeBuilder append(short[] array) {
+ public HashCodeBuilder append(float[] array) {
if (array == null) {
iTotal = iTotal * iConstant;
} else {
@@ -575,12 +797,29 @@
}
/**
- * Append a hashCode
for a char
array.
- *
- * @param array the array to add to the hashCode
+ *
+ * Append a hashCode
for an int
.
+ *
+ *
+ * @param value
+ * the int to add to the hashCode
* @return this
*/
- public HashCodeBuilder append(char[] array) {
+ public HashCodeBuilder append(int value) {
+ iTotal = iTotal * iConstant + value;
+ return this;
+ }
+
+ /**
+ *
+ * Append a hashCode
for an int
array.
+ *
+ *
+ * @param array
+ * the array to add to the hashCode
+ * @return this
+ */
+ public HashCodeBuilder append(int[] array) {
if (array == null) {
iTotal = iTotal * iConstant;
} else {
@@ -592,12 +831,33 @@
}
/**
- * Append a hashCode
for a byte
array.
- *
- * @param array the array to add to the hashCode
+ *
+ * Append a hashCode
for a long
.
+ *
+ *
+ * @param value
+ * the long to add to the hashCode
* @return this
*/
- public HashCodeBuilder append(byte[] array) {
+ // NOTE: This method uses >> and not >>> as Effective Java and
+ // Long.hashCode do. Ideally we should switch to >>> at
+ // some stage. There are backwards compat issues, so
+ // that will have to wait for the time being. cf LANG-342.
+ public HashCodeBuilder append(long value) {
+ iTotal = iTotal * iConstant + ((int) (value ^ (value >> 32)));
+ return this;
+ }
+
+ /**
+ *
+ * Append a hashCode
for a long
array.
+ *
+ *
+ * @param array
+ * the array to add to the hashCode
+ * @return this
+ */
+ public HashCodeBuilder append(long[] array) {
if (array == null) {
iTotal = iTotal * iConstant;
} else {
@@ -609,29 +869,59 @@
}
/**
- * Append a hashCode
for a double
array.
- *
- * @param array the array to add to the hashCode
+ *
+ * Append a hashCode
for an Object
.
+ *
+ *
+ * @param object
+ * the Object to add to the hashCode
* @return this
*/
- public HashCodeBuilder append(double[] array) {
- if (array == null) {
+ public HashCodeBuilder append(Object object) {
+ if (object == null) {
iTotal = iTotal * iConstant;
+
} else {
- for (int i = 0; i < array.length; i++) {
- append(array[i]);
+ if(object.getClass().isArray()) {
+ // 'Switch' on type of array, to dispatch to the correct handler
+ // This handles multi dimensional arrays
+ if (object instanceof long[]) {
+ append((long[]) object);
+ } else if (object instanceof int[]) {
+ append((int[]) object);
+ } else if (object instanceof short[]) {
+ append((short[]) object);
+ } else if (object instanceof char[]) {
+ append((char[]) object);
+ } else if (object instanceof byte[]) {
+ append((byte[]) object);
+ } else if (object instanceof double[]) {
+ append((double[]) object);
+ } else if (object instanceof float[]) {
+ append((float[]) object);
+ } else if (object instanceof boolean[]) {
+ append((boolean[]) object);
+ } else {
+ // Not an array of primitives
+ append((Object[]) object);
+ }
+ } else {
+ iTotal = iTotal * iConstant + object.hashCode();
}
}
return this;
}
/**
- * Append a hashCode
for a float
array.
- *
- * @param array the array to add to the hashCode
+ *
+ * Append a hashCode
for an Object
array.
+ *
+ *
+ * @param array
+ * the array to add to the hashCode
* @return this
*/
- public HashCodeBuilder append(float[] array) {
+ public HashCodeBuilder append(Object[] array) {
if (array == null) {
iTotal = iTotal * iConstant;
} else {
@@ -643,12 +933,29 @@
}
/**
- * Append a hashCode
for a boolean
array.
- *
- * @param array the array to add to the hashCode
+ *
+ * Append a hashCode
for a short
.
+ *
+ *
+ * @param value
+ * the short to add to the hashCode
* @return this
*/
- public HashCodeBuilder append(boolean[] array) {
+ public HashCodeBuilder append(short value) {
+ iTotal = iTotal * iConstant + value;
+ return this;
+ }
+
+ /**
+ *
+ * Append a hashCode
for a short
array.
+ *
+ *
+ * @param array
+ * the array to add to the hashCode
+ * @return this
+ */
+ public HashCodeBuilder append(short[] array) {
if (array == null) {
iTotal = iTotal * iConstant;
} else {
@@ -660,12 +967,42 @@
}
/**
- * Return the computed hashCode
.
- *
+ *
+ * Adds the result of super.hashCode() to this builder.
+ *
+ *
+ * @param superHashCode
+ * the result of calling super.hashCode()
+ * @return this HashCodeBuilder, used to chain calls.
+ * @since 2.0
+ */
+ public HashCodeBuilder appendSuper(int superHashCode) {
+ iTotal = iTotal * iConstant + superHashCode;
+ return this;
+ }
+
+ /**
+ *
+ * Return the computed hashCode
.
+ *
+ *
* @return hashCode
based on the fields appended
*/
public int toHashCode() {
return iTotal;
}
+ /**
+ *
+ * The computed hashCode
from toHashCode() is returned due to the likelyhood
+ * of bugs in mis-calling toHashCode() and the unlikelyness of it mattering what the hashCode for
+ * HashCodeBuilder itself is.
+ *
+ * @return hashCode
based on the fields appended
+ * @since 2.5
+ */
+ public int hashCode() {
+ return toHashCode();
+ }
+
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/IDKey.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/IDKey.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/IDKey.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ *
+ */
+
+package org.apache.commons.lang.builder;
+
+// adapted from org.apache.axis.utils.IDKey
+
+/**
+ * Wrap an identity key (System.identityHashCode())
+ * so that an object can only be equal() to itself.
+ *
+ * This is necessary to disambiguate the occasional duplicate
+ * identityHashCodes that can occur.
+ *
+ * @author Apache Software Foundation
+ */
+final class IDKey {
+ private final Object value;
+ private final int id;
+
+ /**
+ * Constructor for IDKey
+ * @param _value The value
+ */
+ public IDKey(Object _value) {
+ // This is the Object hashcode
+ id = System.identityHashCode(_value);
+ // There have been some cases (LANG-459) that return the
+ // same identity hash code for different objects. So
+ // the value is also added to disambiguate these cases.
+ value = _value;
+ }
+
+ /**
+ * returns hashcode - i.e. the system identity hashcode.
+ * @return the hashcode
+ */
+ public int hashCode() {
+ return id;
+ }
+
+ /**
+ * checks if instances are equal
+ * @param other The other object to compare to
+ * @return if the instances are for the same object
+ */
+ public boolean equals(Object other) {
+ if (!(other instanceof IDKey)) {
+ return false;
+ }
+ IDKey idKey = (IDKey) other;
+ if (id != idKey.id) {
+ return false;
+ }
+ // Note that identity equals is used.
+ return value == idKey.value;
+ }
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/ReflectionToStringBuilder.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/ReflectionToStringBuilder.java (.../ReflectionToStringBuilder.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/ReflectionToStringBuilder.java (.../ReflectionToStringBuilder.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,93 +1,76 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
+
package org.apache.commons.lang.builder;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.ClassUtils;
/**
- *
Assists in implementing {@link Object#toString()} methods using reflection.
- *
- * This class uses reflection to determine the fields to append.
- * Because these fields are usually private, the class
- * uses AccessibleObject.setAccessible
to
- * change the visibility of the fields. This will fail under a security manager,
- * unless the appropriate permissions are set up correctly.
- *
- * A typical invocation for this method would look like:
+ *
+ * Assists in implementing {@link Object#toString()} methods using reflection.
+ *
+ *
+ *
+ * This class uses reflection to determine the fields to append. Because these fields are usually private, the class
+ * uses {@link java.lang.reflect.AccessibleObject#setAccessible(java.lang.reflect.AccessibleObject[], boolean)} to
+ * change the visibility of the fields. This will fail under a security manager, unless the appropriate permissions are
+ * set up correctly.
+ *
+ *
+ *
+ * A typical invocation for this method would look like:
+ *
+ *
*
* public String toString() {
* return ReflectionToStringBuilder.toString(this);
* }
- *
- * You can also use the builder to debug 3rd party objects:
+ *
+ *
+ *
+ *
+ * You can also use the builder to debug 3rd party objects:
+ *
+ *
*
* System.out.println("An object: " + ReflectionToStringBuilder.toString(anObject));
*
- * A subclass can control field output by overriding the methods:
- *
- * - {@link #accept(java.lang.reflect.Field)}
- * - {@link #getValue(java.lang.reflect.Field)}
+ *
+ *
+ *
+ * A subclass can control field output by overriding the methods:
+ *
+ * - {@link #accept(java.lang.reflect.Field)}
+ * - {@link #getValue(java.lang.reflect.Field)}
*
*
- * For example, this method does not include the password
field in the returned
- * String
:
+ *
+ * For example, this method does not include the password
field in the returned
+ * String
:
+ *
+ *
*
* public String toString() {
* return (new ReflectionToStringBuilder(this) {
@@ -97,241 +80,415 @@
* }).toString();
* }
*
- * The exact format of the toString
is determined by
- * the {@link ToStringStyle} passed into the constructor.
- *
+ *
+ *
+ *
+ * The exact format of the toString
is determined by the {@link ToStringStyle} passed into the
+ * constructor.
+ *
+ *
+ * @author Apache Software Foundation
* @author Gary Gregory
- * @author Stephen Colebourne
* @author Pete Gieser
* @since 2.0
* @version $Id$
*/
public class ReflectionToStringBuilder extends ToStringBuilder {
/**
- * A registry of objects used by reflectionToString
methods
- * to detect cyclical object references and avoid infinite loops.
+ *
+ * Builds a toString
value using the default ToStringStyle
through reflection.
+ *
+ *
+ *
+ * It uses AccessibleObject.setAccessible
to gain access to private fields. This means that it will
+ * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
+ * also not as efficient as testing explicitly.
+ *
+ *
+ *
+ * Transient members will be not be included, as they are likely derived. Static fields will not be included.
+ * Superclass fields will be appended.
+ *
+ *
+ * @param object
+ * the Object to be output
+ * @return the String result
+ * @throws IllegalArgumentException
+ * if the Object is null
*/
- private static ThreadLocal registry = new ThreadLocal() {
- protected synchronized Object initialValue() {
- // The HashSet implementation is not synchronized,
- // which is just what we need here.
- return new HashSet();
- }
- };
+ public static String toString(Object object) {
+ return toString(object, null, false, false, null);
+ }
/**
- * Returns the registry of objects being traversed by the
- * reflectionToString
methods in the current thread.
- *
- * @return Set the registry of objects being traversed
+ *
+ * Builds a toString
value through reflection.
+ *
+ *
+ *
+ * It uses AccessibleObject.setAccessible
to gain access to private fields. This means that it will
+ * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
+ * also not as efficient as testing explicitly.
+ *
+ *
+ *
+ * Transient members will be not be included, as they are likely derived. Static fields will not be included.
+ * Superclass fields will be appended.
+ *
+ *
+ *
+ * If the style is null
, the default ToStringStyle
is used.
+ *
+ *
+ * @param object
+ * the Object to be output
+ * @param style
+ * the style of the toString
to create, may be null
+ * @return the String result
+ * @throws IllegalArgumentException
+ * if the Object or ToStringStyle
is null
*/
- static Set getRegistry() {
- return (Set) registry.get();
+ public static String toString(Object object, ToStringStyle style) {
+ return toString(object, style, false, false, null);
}
/**
- * Returns true
if the registry contains the given object.
- * Used by the reflection methods to avoid infinite loops.
+ *
+ * Builds a toString
value through reflection.
+ *
*
- * @param value The object to lookup in the registry.
- * @return boolean true
if the registry contains the given object.
+ *
+ * It uses AccessibleObject.setAccessible
to gain access to private fields. This means that it will
+ * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
+ * also not as efficient as testing explicitly.
+ *
+ *
+ *
+ * If the outputTransients
is true
, transient members will be output, otherwise they
+ * are ignored, as they are likely derived fields, and not part of the value of the Object.
+ *
+ *
+ *
+ * Static fields will not be included. Superclass fields will be appended.
+ *
+ *
+ *
+ * If the style is null
, the default ToStringStyle
is used.
+ *
+ *
+ * @param object
+ * the Object to be output
+ * @param style
+ * the style of the toString
to create, may be null
+ * @param outputTransients
+ * whether to include transient fields
+ * @return the String result
+ * @throws IllegalArgumentException
+ * if the Object is null
*/
- static boolean isRegistered(Object value) {
- return getRegistry().contains(value);
+ public static String toString(Object object, ToStringStyle style, boolean outputTransients) {
+ return toString(object, style, outputTransients, false, null);
}
/**
- * Registers the given object.
- * Used by the reflection methods to avoid infinite loops.
+ *
+ * Builds a toString
value through reflection.
+ *
*
- * @param value The object to register.
+ *
+ * It uses AccessibleObject.setAccessible
to gain access to private fields. This means that it will
+ * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
+ * also not as efficient as testing explicitly.
+ *
+ *
+ *
+ * If the outputTransients
is true
, transient fields will be output, otherwise they
+ * are ignored, as they are likely derived fields, and not part of the value of the Object.
+ *
+ *
+ *
+ * If the outputStatics
is true
, static fields will be output, otherwise they are
+ * ignored.
+ *
+ *
+ *
+ * Static fields will not be included. Superclass fields will be appended.
+ *
+ *
+ *
+ * If the style is null
, the default ToStringStyle
is used.
+ *
+ *
+ * @param object
+ * the Object to be output
+ * @param style
+ * the style of the toString
to create, may be null
+ * @param outputTransients
+ * whether to include transient fields
+ * @param outputStatics
+ * whether to include transient fields
+ * @return the String result
+ * @throws IllegalArgumentException
+ * if the Object is null
+ * @since 2.1
*/
- static void register(Object value) {
- getRegistry().add(value);
+ public static String toString(Object object, ToStringStyle style, boolean outputTransients, boolean outputStatics) {
+ return toString(object, style, outputTransients, outputStatics, null);
}
-
+
/**
- * This method uses reflection to build a suitable
- * toString
using the default ToStringStyle
.
- *
- *
It uses AccessibleObject.setAccessible
to gain access to private
- * fields. This means that it will throw a security exception if run
- * under a security manager, if the permissions are not set up correctly.
- * It is also not as efficient as testing explicitly.
- *
- * Transient members will be not be included, as they are likely derived.
- * Static fields will not be included. Superclass fields will be appended.
- *
- * @param object the Object to be output
+ *
+ * Builds a toString
value through reflection.
+ *
+ *
+ *
+ * It uses AccessibleObject.setAccessible
to gain access to private fields. This means that it will
+ * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
+ * also not as efficient as testing explicitly.
+ *
+ *
+ *
+ * If the outputTransients
is true
, transient fields will be output, otherwise they
+ * are ignored, as they are likely derived fields, and not part of the value of the Object.
+ *
+ *
+ *
+ * If the outputStatics
is true
, static fields will be output, otherwise they are
+ * ignored.
+ *
+ *
+ *
+ * Superclass fields will be appended up to and including the specified superclass. A null superclass is treated as
+ * java.lang.Object
.
+ *
+ *
+ *
+ * If the style is null
, the default ToStringStyle
is used.
+ *
+ *
+ * @param object
+ * the Object to be output
+ * @param style
+ * the style of the toString
to create, may be null
+ * @param outputTransients
+ * whether to include transient fields
+ * @param outputStatics
+ * whether to include static fields
+ * @param reflectUpToClass
+ * the superclass to reflect up to (inclusive), may be null
* @return the String result
- * @throws IllegalArgumentException if the Object is null
+ * @throws IllegalArgumentException
+ * if the Object is null
+ * @since 2.1
*/
- public static String toString(Object object) {
- return toString(object, null, false, null);
+ public static String toString(Object object, ToStringStyle style, boolean outputTransients, boolean outputStatics,
+ Class reflectUpToClass) {
+ return new ReflectionToStringBuilder(object, style, null, reflectUpToClass, outputTransients, outputStatics)
+ .toString();
}
/**
- * This method uses reflection to build a suitable
- * toString
.
- *
- * It uses AccessibleObject.setAccessible
to gain access to private
- * fields. This means that it will throw a security exception if run
- * under a security manager, if the permissions are not set up correctly.
- * It is also not as efficient as testing explicitly.
- *
- * Transient members will be not be included, as they are likely derived.
- * Static fields will not be included. Superclass fields will be appended.
- *
- * If the style is null
, the default
- * ToStringStyle
is used.
+ *
+ * Builds a toString
value through reflection.
+ *
*
- * @param object the Object to be output
- * @param style the style of the toString
to create,
- * may be null
+ *
+ * It uses AccessibleObject.setAccessible
to gain access to private fields. This means that it will
+ * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
+ * also not as efficient as testing explicitly.
+ *
+ *
+ *
+ * If the outputTransients
is true
, transient members will be output, otherwise they
+ * are ignored, as they are likely derived fields, and not part of the value of the Object.
+ *
+ *
+ *
+ * Static fields will not be included. Superclass fields will be appended up to and including the specified
+ * superclass. A null superclass is treated as java.lang.Object
.
+ *
+ *
+ *
+ * If the style is null
, the default ToStringStyle
is used.
+ *
+ *
+ * @deprecated Use {@link #toString(Object,ToStringStyle,boolean,boolean,Class)}
+ *
+ * @param object
+ * the Object to be output
+ * @param style
+ * the style of the toString
to create, may be null
+ * @param outputTransients
+ * whether to include transient fields
+ * @param reflectUpToClass
+ * the superclass to reflect up to (inclusive), may be null
* @return the String result
- * @throws IllegalArgumentException if the Object or
- * ToStringStyle
is null
+ * @throws IllegalArgumentException
+ * if the Object is null
+ * @since 2.0
*/
- public static String toString(Object object, ToStringStyle style) {
- return toString(object, style, false, null);
+ public static String toString(Object object, ToStringStyle style,
+ boolean outputTransients, Class reflectUpToClass)
+ {
+ return new ReflectionToStringBuilder(object, style, null, reflectUpToClass, outputTransients).toString();
}
/**
- * This method uses reflection to build a suitable
- * toString
.
- *
- * It uses AccessibleObject.setAccessible
to gain access to private
- * fields. This means that it will throw a security exception if run
- * under a security manager, if the permissions are not set up correctly.
- * It is also not as efficient as testing explicitly.
- *
- * If the outputTransients
is true
,
- * transient members will be output, otherwise they are ignored,
- * as they are likely derived fields, and not part of the value of the
- * Object.
- *
- * Static fields will not be included. Superclass fields will be appended.
- *
- * If the style is null
, the default
- * ToStringStyle
is used.
+ * Builds a String for a toString method excluding the given field name.
*
- * @param object the Object to be output
- * @param style the style of the toString
to create,
- * may be null
- * @param outputTransients whether to include transient fields
- * @return the String result
- * @throws IllegalArgumentException if the Object is null
+ * @param object
+ * The object to "toString".
+ * @param excludeFieldName
+ * The field name to exclude
+ * @return The toString value.
*/
- public static String toString(Object object, ToStringStyle style, boolean outputTransients) {
- return toString(object, style, outputTransients, null);
+ public static String toStringExclude(Object object, final String excludeFieldName) {
+ return toStringExclude(object, new String[]{excludeFieldName});
}
/**
- * This method uses reflection to build a suitable
- * toString
.
- *
- * It uses AccessibleObject.setAccessible
to gain access to private
- * fields. This means that it will throw a security exception if run
- * under a security manager, if the permissions are not set up correctly.
- * It is also not as efficient as testing explicitly.
- *
- * If the outputTransients
is true
,
- * transient members will be output, otherwise they are ignored,
- * as they are likely derived fields, and not part of the value of the
- * Object.
- *
- * Static fields will not be included. Superclass fields will be appended
- * up to and including the specified superclass. A null superclass is treated
- * as java.lang.Object
.
- *
- * If the style is null
, the default
- * ToStringStyle
is used.
+ * Builds a String for a toString method excluding the given field names.
*
- * @param object the Object to be output
- * @param style the style of the toString
to create,
- * may be null
- * @param outputTransients whether to include transient fields
- * @param reflectUpToClass the superclass to reflect up to (inclusive),
- * may be null
- * @return the String result
- * @throws IllegalArgumentException if the Object is null
+ * @param object
+ * The object to "toString".
+ * @param excludeFieldNames
+ * The field names to exclude. Null excludes nothing.
+ * @return The toString value.
*/
- public static String toString(
- Object object,
- ToStringStyle style,
- boolean outputTransients,
- Class reflectUpToClass) {
- return new ReflectionToStringBuilder(object, style, null, reflectUpToClass, outputTransients).toString();
+ public static String toStringExclude(Object object, Collection /*String*/ excludeFieldNames) {
+ return toStringExclude(object, toNoNullStringArray(excludeFieldNames));
}
/**
- * Unregisters the given object.
- *
- * Used by the reflection methods to avoid infinite loops.
+ * Converts the given Collection into an array of Strings. The returned array does not contain null
+ * entries. Note that {@link Arrays#sort(Object[])} will throw an {@link NullPointerException} if an array element
+ * is null
.
*
- * @param value The object to unregister.
+ * @param collection
+ * The collection to convert
+ * @return A new array of Strings.
*/
- static void unregister(Object value) {
- getRegistry().remove(value);
+ static String[] toNoNullStringArray(Collection collection) {
+ if (collection == null) {
+ return ArrayUtils.EMPTY_STRING_ARRAY;
+ }
+ return toNoNullStringArray(collection.toArray());
}
/**
+ * Returns a new array of Strings without null elements. Internal method used to normalize exclude lists
+ * (arrays and collections). Note that {@link Arrays#sort(Object[])} will throw an {@link NullPointerException}
+ * if an array element is null
.
+ *
+ * @param array
+ * The array to check
+ * @return The given array or a new array without null.
+ */
+ static String[] toNoNullStringArray(Object[] array) {
+ ArrayList list = new ArrayList(array.length);
+ for (int i = 0; i < array.length; i++) {
+ Object e = array[i];
+ if (e != null) {
+ list.add(e.toString());
+ }
+ }
+ return (String[]) list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
+ }
+
+
+ /**
+ * Builds a String for a toString method excluding the given field names.
+ *
+ * @param object
+ * The object to "toString".
+ * @param excludeFieldNames
+ * The field names to exclude
+ * @return The toString value.
+ */
+ public static String toStringExclude(Object object, String[] excludeFieldNames) {
+ return new ReflectionToStringBuilder(object).setExcludeFieldNames(excludeFieldNames).toString();
+ }
+
+ /**
+ * Whether or not to append static fields.
+ */
+ private boolean appendStatics = false;
+
+ /**
* Whether or not to append transient fields.
*/
private boolean appendTransients = false;
/**
+ * Which field names to exclude from output. Intended for fields like "password"
.
+ */
+ private String[] excludeFieldNames;
+
+ /**
* The last super class to stop appending fields for.
*/
private Class upToClass = null;
/**
- * Constructor.
- *
- * This constructor outputs using the default style set with
- * setDefaultStyle
.
+ *
+ * Constructor.
+ *
*
- * @param object the Object to build a toString
for,
- * must not be null
- * @throws IllegalArgumentException if the Object passed in is
- * null
+ *
+ * This constructor outputs using the default style set with setDefaultStyle
.
+ *
+ *
+ * @param object
+ * the Object to build a toString
for, must not be null
+ * @throws IllegalArgumentException
+ * if the Object passed in is null
*/
public ReflectionToStringBuilder(Object object) {
super(object);
}
/**
- * Constructor.
- *
- * If the style is null
, the default style is used.
+ *
+ * Constructor.
+ *
*
- * @param object the Object to build a toString
for,
- * must not be null
- * @param style the style of the toString
to create,
- * may be null
- * @throws IllegalArgumentException if the Object passed in is
- * null
+ *
+ * If the style is null
, the default style is used.
+ *
+ *
+ * @param object
+ * the Object to build a toString
for, must not be null
+ * @param style
+ * the style of the toString
to create, may be null
+ * @throws IllegalArgumentException
+ * if the Object passed in is null
*/
public ReflectionToStringBuilder(Object object, ToStringStyle style) {
super(object, style);
}
/**
- * Constructor.
- *
- * If the style is null
, the default style is used.
- *
- * If the buffer is null
, a new one is created.
+ *
+ * Constructor.
+ *
*
- * @param object the Object to build a toString
for,
- * must not be null
- * @param style the style of the toString
to create,
- * may be null
- * @param buffer the StringBuffer
to populate, may be
- * null
- * @throws IllegalArgumentException if the Object passed in is
- * null
+ *
+ * If the style is null
, the default style is used.
+ *
+ *
+ *
+ * If the buffer is null
, a new one is created.
+ *
+ *
+ * @param object
+ * the Object to build a toString
for
+ * @param style
+ * the style of the toString
to create, may be null
+ * @param buffer
+ * the StringBuffer
to populate, may be null
+ * @throws IllegalArgumentException
+ * if the Object passed in is null
*/
public ReflectionToStringBuilder(Object object, ToStringStyle style, StringBuffer buffer) {
super(object, style, buffer);
@@ -340,107 +497,135 @@
/**
* Constructor.
*
- * @param object the Object to build a toString
for,
- * must not be null
- * @param style the style of the toString
to create,
- * may be null
- * @param buffer the StringBuffer
to populate, may be
- * null
- * @param reflectUpToClass the superclass to reflect up to (inclusive),
- * may be null
- * @param outputTransients whether to include transient fields
+ * @deprecated Use {@link #ReflectionToStringBuilder(Object,ToStringStyle,StringBuffer,Class,boolean,boolean)}.
+ *
+ * @param object
+ * the Object to build a toString
for
+ * @param style
+ * the style of the toString
to create, may be null
+ * @param buffer
+ * the StringBuffer
to populate, may be null
+ * @param reflectUpToClass
+ * the superclass to reflect up to (inclusive), may be null
+ * @param outputTransients
+ * whether to include transient fields
*/
- public ReflectionToStringBuilder(
- Object object,
- ToStringStyle style,
- StringBuffer buffer,
- Class reflectUpToClass,
- boolean outputTransients) {
+ public ReflectionToStringBuilder(Object object, ToStringStyle style, StringBuffer buffer, Class reflectUpToClass,
+ boolean outputTransients) {
super(object, style, buffer);
this.setUpToClass(reflectUpToClass);
this.setAppendTransients(outputTransients);
}
/**
+ * Constructor.
+ *
+ * @param object
+ * the Object to build a toString
for
+ * @param style
+ * the style of the toString
to create, may be null
+ * @param buffer
+ * the StringBuffer
to populate, may be null
+ * @param reflectUpToClass
+ * the superclass to reflect up to (inclusive), may be null
+ * @param outputTransients
+ * whether to include transient fields
+ * @param outputStatics
+ * whether to include static fields
+ * @since 2.1
+ */
+ public ReflectionToStringBuilder(Object object, ToStringStyle style, StringBuffer buffer, Class reflectUpToClass,
+ boolean outputTransients, boolean outputStatics) {
+ super(object, style, buffer);
+ this.setUpToClass(reflectUpToClass);
+ this.setAppendTransients(outputTransients);
+ this.setAppendStatics(outputStatics);
+ }
+
+ /**
* Returns whether or not to append the given Field
.
*
- * - Static fields are not appended.
- * - Transient fields are appended only if {@link #isAppendTransients()} returns
true
.
- * - Inner class fields are not appened.
+ * - Transient fields are appended only if {@link #isAppendTransients()} returns
true
.
+ * - Static fields are appended only if {@link #isAppendStatics()} returns
true
.
+ * - Inner class fields are not appened.
*
- * @param field The Field to test.
+ *
+ * @param field
+ * The Field to test.
* @return Whether or not to append the given Field
.
*/
protected boolean accept(Field field) {
- String fieldName = field.getName();
- return (fieldName.indexOf(ClassUtils.INNER_CLASS_SEPARATOR_CHAR) == -1)
- && (this.isAppendTransients() || !Modifier.isTransient(field.getModifiers()))
- && (!Modifier.isStatic(field.getModifiers()));
+ if (field.getName().indexOf(ClassUtils.INNER_CLASS_SEPARATOR_CHAR) != -1) {
+ // Reject field from inner class.
+ return false;
+ }
+ if (Modifier.isTransient(field.getModifiers()) && !this.isAppendTransients()) {
+ // Reject transient fields.
+ return false;
+ }
+ if (Modifier.isStatic(field.getModifiers()) && !this.isAppendStatics()) {
+ // Reject static fields.
+ return false;
+ }
+ if (this.getExcludeFieldNames() != null
+ && Arrays.binarySearch(this.getExcludeFieldNames(), field.getName()) >= 0) {
+ // Reject fields from the getExcludeFieldNames list.
+ return false;
+ }
+ return true;
}
/**
- * Appends the fields and values defined by the given object of the
- * given Class.
- *
- * If a cycle is detected as an object is "toString()'ed",
- * such an object is rendered as if Object.toString()
- * had been called and not implemented by the object.
+ *
+ * Appends the fields and values defined by the given object of the given Class.
+ *
*
- * @param clazz The class of object parameter
+ *
+ * If a cycle is detected as an object is "toString()'ed", such an object is rendered as if
+ * Object.toString()
had been called and not implemented by the object.
+ *
+ *
+ * @param clazz
+ * The class of object parameter
*/
protected void appendFieldsIn(Class clazz) {
- if (isRegistered(this.getObject())) {
- // The object has already been appended, therefore we have an object cycle.
- // Append a simple Object.toString style string. The field name is already appended at this point.
- this.appendAsObjectToString(this.getObject());
+ if (clazz.isArray()) {
+ this.reflectionAppendArray(this.getObject());
return;
}
- try {
- this.registerObject();
- if (clazz.isArray()) {
- this.reflectionAppendArray(this.getObject());
- return;
- }
- Field[] fields = clazz.getDeclaredFields();
- AccessibleObject.setAccessible(fields, true);
- for (int i = 0; i < fields.length; i++) {
- Field field = fields[i];
- String fieldName = field.getName();
- if (this.accept(field)) {
- try {
- // Warning: Field.get(Object) creates wrappers objects for primitive types.
- Object fieldValue = this.getValue(field);
- if (isRegistered(fieldValue) && !field.getType().isPrimitive()) {
- // A known field value has already been appended, therefore we have an object cycle,
- // append a simple Object.toString style string.
- this.getStyle().appendFieldStart(this.getStringBuffer(), fieldName);
- this.appendAsObjectToString(fieldValue);
- // The recursion out of
- // builder.append(fieldName, fieldValue);
- // below will append the field
- // end marker.
- } else {
- try {
- this.registerObject();
- this.append(fieldName, fieldValue);
- } finally {
- this.unregisterObject();
- }
- }
- } catch (IllegalAccessException ex) {
- //this can't happen. Would get a Security exception instead
- //throw a runtime exception in case the impossible happens.
- throw new InternalError("Unexpected IllegalAccessException: " + ex.getMessage());
- }
+ Field[] fields = clazz.getDeclaredFields();
+ AccessibleObject.setAccessible(fields, true);
+ for (int i = 0; i < fields.length; i++) {
+ Field field = fields[i];
+ String fieldName = field.getName();
+ if (this.accept(field)) {
+ try {
+ // Warning: Field.get(Object) creates wrappers objects
+ // for primitive types.
+ Object fieldValue = this.getValue(field);
+ this.append(fieldName, fieldValue);
+ } catch (IllegalAccessException ex) {
+ //this can't happen. Would get a Security exception
+ // instead
+ //throw a runtime exception in case the impossible
+ // happens.
+ throw new InternalError("Unexpected IllegalAccessException: " + ex.getMessage());
}
}
- } finally {
- this.unregisterObject();
}
}
-
+
/**
- * Gets the last super class to stop appending fields for.
+ * @return Returns the excludeFieldNames.
+ */
+ public String[] getExcludeFieldNames() {
+ return this.excludeFieldNames;
+ }
+
+ /**
+ *
+ * Gets the last super class to stop appending fields for.
+ *
*
* @return The last super class to stop appending fields for.
*/
@@ -449,30 +634,55 @@
}
/**
- * Calls java.lang.reflect.Field.get(Object)
.
- *
- * @see java.lang.reflect.Field#get(Object)
+ *
+ * Calls java.lang.reflect.Field.get(Object)
.
+ *
+ *
+ * @param field
+ * The Field to query.
+ * @return The Object from the given Field.
+ *
* @throws IllegalArgumentException
+ * see {@link java.lang.reflect.Field#get(Object)}
* @throws IllegalAccessException
+ * see {@link java.lang.reflect.Field#get(Object)}
+ *
+ * @see java.lang.reflect.Field#get(Object)
*/
protected Object getValue(Field field) throws IllegalArgumentException, IllegalAccessException {
return field.get(this.getObject());
}
/**
- * Gets whether or not to append transient fields.
+ *
+ * Gets whether or not to append static fields.
+ *
*
+ * @return Whether or not to append static fields.
+ * @since 2.1
+ */
+ public boolean isAppendStatics() {
+ return this.appendStatics;
+ }
+
+ /**
+ *
+ * Gets whether or not to append transient fields.
+ *
+ *
* @return Whether or not to append transient fields.
*/
public boolean isAppendTransients() {
return this.appendTransients;
}
-
+
/**
- * Append to the toString
an Object
- * array.
- *
- * @param array the array to add to the toString
+ *
+ * Append to the toString
an Object
array.
+ *
+ *
+ * @param array
+ * the array to add to the toString
* @return this
*/
public ToStringBuilder reflectionAppendArray(Object array) {
@@ -481,34 +691,70 @@
}
/**
- * Registers this builder's source object to avoid infinite
- * loops when processing circular object references.
+ *
+ * Sets whether or not to append static fields.
+ *
+ *
+ * @param appendStatics
+ * Whether or not to append static fields.
+ * @since 2.1
*/
- void registerObject() {
- register(this.getObject());
+ public void setAppendStatics(boolean appendStatics) {
+ this.appendStatics = appendStatics;
}
/**
- * Sets whether or not to append transient fields.
+ *
+ * Sets whether or not to append transient fields.
+ *
*
- * @param appendTransients Whether or not to append transient fields.
+ * @param appendTransients
+ * Whether or not to append transient fields.
*/
public void setAppendTransients(boolean appendTransients) {
this.appendTransients = appendTransients;
}
/**
- * Sets the last super class to stop appending fields for.
+ * Sets the field names to exclude.
*
- * @param clazz The last super class to stop appending fields for.
+ * @param excludeFieldNamesParam
+ * The excludeFieldNames to excluding from toString or null
.
+ * @return this
*/
+ public ReflectionToStringBuilder setExcludeFieldNames(String[] excludeFieldNamesParam) {
+ if (excludeFieldNamesParam == null) {
+ this.excludeFieldNames = null;
+ } else {
+ this.excludeFieldNames = toNoNullStringArray(excludeFieldNamesParam);
+ Arrays.sort(this.excludeFieldNames);
+ }
+ return this;
+ }
+
+ /**
+ *
+ * Sets the last super class to stop appending fields for.
+ *
+ *
+ * @param clazz
+ * The last super class to stop appending fields for.
+ */
public void setUpToClass(Class clazz) {
+ if (clazz != null) {
+ Object object = getObject();
+ if (object != null && clazz.isInstance(object) == false) {
+ throw new IllegalArgumentException("Specified class is not a superclass of the object");
+ }
+ }
this.upToClass = clazz;
}
/**
- * Gets the String built by this builder.
- *
+ *
+ * Gets the String built by this builder.
+ *
+ *
* @return the built string
*/
public String toString() {
@@ -524,12 +770,4 @@
return super.toString();
}
- /**
- * Unegisters this builder's source object to avoid infinite
- * loops when processing circular object references.
- */
- void unregisterObject() {
- unregister(this.getObject());
- }
-
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/StandardToStringStyle.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/StandardToStringStyle.java (.../StandardToStringStyle.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/StandardToStringStyle.java (.../StandardToStringStyle.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,55 +1,18 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang.builder;
@@ -62,7 +25,7 @@
* store the result in a public static final variable for the rest of the
* program to access.
*
- * @author Stephen Colebourne
+ * @author Apache Software Foundation
* @author Pete Gieser
* @author Gary Gregory
* @since 1.0
@@ -71,6 +34,13 @@
public class StandardToStringStyle extends ToStringStyle {
/**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
* Constructor.
*/
public StandardToStringStyle() {
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/ToStringBuilder.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/ToStringBuilder.java (.../ToStringBuilder.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/ToStringBuilder.java (.../ToStringBuilder.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,55 +1,18 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang.builder;
@@ -76,7 +39,7 @@
* public class Person {
* String name;
* int age;
- * boolean isSmoker;
+ * boolean smoker;
*
* ...
*
@@ -121,7 +84,7 @@
* The exact format of the toString
is determined by
* the {@link ToStringStyle} passed into the constructor.
*
- * @author Stephen Colebourne
+ * @author Apache Software Foundation
* @author Gary Gregory
* @author Pete Gieser
* @since 1.0
@@ -130,150 +93,166 @@
public class ToStringBuilder {
/**
- * The default style of output to use.
+ * The default style of output to use, not null.
*/
- private static ToStringStyle defaultStyle = ToStringStyle.DEFAULT_STYLE;
+ private static volatile ToStringStyle defaultStyle = ToStringStyle.DEFAULT_STYLE;
//----------------------------------------------------------------------------
/**
* Gets the default ToStringStyle
to use.
- *
- * This could allow the ToStringStyle
to be
- * controlled for an entire application with one call.
- *
- * This might be used to have a verbose
- * ToStringStyle
during development and a compact
- * ToStringStyle
in production.
*
- * @return the default ToStringStyle
+ * This method gets a singleton default value, typically for the whole JVM.
+ * Changing this default should generally only be done during application startup.
+ * It is recommended to pass a ToStringStyle
to the constructor instead
+ * of using this global default.
+ *
+ * This method can be used from multiple threads.
+ * Internally, a volatile
variable is used to provide the guarantee
+ * that the latest value set using {@link #setDefaultStyle} is the value returned.
+ * It is strongly recommended that the default style is only changed during application startup.
+ *
+ * One reason for changing the default could be to have a verbose style during
+ * development and a compact style in production.
+ *
+ * @return the default ToStringStyle
, never null
*/
public static ToStringStyle getDefaultStyle() {
return defaultStyle;
}
/**
- * Forwards to ReflectionToStringBuilder
.
+ * Sets the default ToStringStyle
to use.
*
+ * This method sets a singleton default value, typically for the whole JVM.
+ * Changing this default should generally only be done during application startup.
+ * It is recommended to pass a ToStringStyle
to the constructor instead
+ * of changing this global default.
+ *
+ * This method is not intended for use from multiple threads.
+ * Internally, a volatile
variable is used to provide the guarantee
+ * that the latest value set is the value returned from {@link #getDefaultStyle}.
+ *
+ * @param style the default ToStringStyle
+ * @throws IllegalArgumentException if the style is null
+ */
+ public static void setDefaultStyle(ToStringStyle style) {
+ if (style == null) {
+ throw new IllegalArgumentException("The style must not be null");
+ }
+ defaultStyle = style;
+ }
+
+ //----------------------------------------------------------------------------
+ /**
+ * Uses ReflectionToStringBuilder
to generate a
+ * toString
for the specified object.
+ *
+ * @param object the Object to be output
+ * @return the String result
* @see ReflectionToStringBuilder#toString(Object)
*/
public static String reflectionToString(Object object) {
return ReflectionToStringBuilder.toString(object);
}
/**
- * Forwards to ReflectionToStringBuilder
.
+ * Uses ReflectionToStringBuilder
to generate a
+ * toString
for the specified object.
*
+ * @param object the Object to be output
+ * @param style the style of the toString
to create, may be null
+ * @return the String result
* @see ReflectionToStringBuilder#toString(Object,ToStringStyle)
*/
public static String reflectionToString(Object object, ToStringStyle style) {
return ReflectionToStringBuilder.toString(object, style);
}
/**
- * Forwards to ReflectionToStringBuilder
.
+ * Uses ReflectionToStringBuilder
to generate a
+ * toString
for the specified object.
*
+ * @param object the Object to be output
+ * @param style the style of the toString
to create, may be null
+ * @param outputTransients whether to include transient fields
+ * @return the String result
* @see ReflectionToStringBuilder#toString(Object,ToStringStyle,boolean)
*/
public static String reflectionToString(Object object, ToStringStyle style, boolean outputTransients) {
- return ReflectionToStringBuilder.toString(object, style, outputTransients, null);
+ return ReflectionToStringBuilder.toString(object, style, outputTransients, false, null);
}
/**
- * Forwards to ReflectionToStringBuilder
.
+ * Uses ReflectionToStringBuilder
to generate a
+ * toString
for the specified object.
*
- * @see ReflectionToStringBuilder#toString(Object,ToStringStyle,boolean,Class)
+ * @param object the Object to be output
+ * @param style the style of the toString
to create, may be null
+ * @param outputTransients whether to include transient fields
+ * @param reflectUpToClass the superclass to reflect up to (inclusive), may be null
+ * @return the String result
+ * @see ReflectionToStringBuilder#toString(Object,ToStringStyle,boolean,boolean,Class)
* @since 2.0
*/
public static String reflectionToString(
Object object,
ToStringStyle style,
boolean outputTransients,
Class reflectUpToClass) {
- return ReflectionToStringBuilder.toString(object, style, outputTransients, reflectUpToClass);
+ return ReflectionToStringBuilder.toString(object, style, outputTransients, false, reflectUpToClass);
}
- /**
- * Sets the default ToStringStyle
to use.
- *
- * @param style the default ToStringStyle
- * @throws IllegalArgumentException if the style is null
- */
- public static void setDefaultStyle(ToStringStyle style) {
- if (style == null) {
- throw new IllegalArgumentException("The style must not be null");
- }
- defaultStyle = style;
- }
+ //----------------------------------------------------------------------------
/**
- * Current toString buffer.
+ * Current toString buffer, not null.
*/
private final StringBuffer buffer;
-
/**
- * The object being output.
+ * The object being output, may be null.
*/
private final Object object;
-
/**
- * The style of output to use.
+ * The style of output to use, not null.
*/
private final ToStringStyle style;
/**
- * Constructor for ToStringBuilder
.
+ * Constructs a builder for the specified object using the default output style.
*
- * This constructor outputs using the default style set with
- * setDefaultStyle
.
+ * This default style is obtained from {@link #getDefaultStyle()}.
*
- * @param object the Object to build a toString
for,
- * must not be null
- * @throws IllegalArgumentException if the Object passed in is
- * null
+ * @param object the Object to build a toString
for, not recommended to be null
*/
public ToStringBuilder(Object object) {
- this(object, getDefaultStyle(), null);
+ this(object, null, null);
}
/**
- * Constructor for ToStringBuilder
specifying the
- * output style.
+ * Constructs a builder for the specified object using the a defined output style.
*
* If the style is null
, the default style is used.
*
- * @param object the Object to build a toString
for,
- * must not be null
- * @param style the style of the toString
to create,
- * may be null
- * @throws IllegalArgumentException if the Object passed in is
- * null
+ * @param object the Object to build a toString
for, not recommended to be null
+ * @param style the style of the toString
to create, null uses the default style
*/
public ToStringBuilder(Object object, ToStringStyle style) {
this(object, style, null);
}
/**
- * Constructor for ToStringBuilder
.
+ * Constructs a builder for the specified object.
*
* If the style is null
, the default style is used.
*
* If the buffer is null
, a new one is created.
*
- * @param object the Object to build a toString
for,
- * must not be null
- * @param style the style of the toString
to create,
- * may be null
- * @param buffer the StringBuffer
to populate, may be
- * null
- * @throws IllegalArgumentException if the Object passed in is
- * null
+ * @param object the Object to build a toString
for, not recommended to be null
+ * @param style the style of the toString
to create, null uses the default style
+ * @param buffer the StringBuffer
to populate, may be null
*/
public ToStringBuilder(Object object, ToStringStyle style, StringBuffer buffer) {
- super();
- if (object == null) {
- throw new IllegalArgumentException("The object to create a toString for must not be null");
- }
if (style == null) {
style = getDefaultStyle();
}
@@ -489,11 +468,11 @@
* Append to the toString
an Object
* value.
*
- * @param object the value to add to the toString
+ * @param obj the value to add to the toString
* @return this
*/
- public ToStringBuilder append(Object object) {
- style.append(buffer, null, object, null);
+ public ToStringBuilder append(Object obj) {
+ style.append(buffer, null, obj, null);
return this;
}
@@ -865,11 +844,11 @@
* value.
*
* @param fieldName the field name
- * @param object the value to add to the toString
+ * @param obj the value to add to the toString
* @return this
*/
- public ToStringBuilder append(String fieldName, Object object) {
- style.append(buffer, fieldName, object, null);
+ public ToStringBuilder append(String fieldName, Object obj) {
+ style.append(buffer, fieldName, obj, null);
return this;
}
@@ -878,13 +857,13 @@
* value.
*
* @param fieldName the field name
- * @param object the value to add to the toString
+ * @param obj the value to add to the toString
* @param fullDetail true
for detail,
* false
for summary info
* @return this
*/
- public ToStringBuilder append(String fieldName, Object object, boolean fullDetail) {
- style.append(buffer, fieldName, object, BooleanUtils.toBooleanObject(fullDetail));
+ public ToStringBuilder append(String fieldName, Object obj, boolean fullDetail) {
+ style.append(buffer, fieldName, obj, BooleanUtils.toBooleanObject(fullDetail));
return this;
}
@@ -973,10 +952,11 @@
* {@link System#identityHashCode(java.lang.Object)}.
*
* @param object the Object
whose class name and id to output
+ * @return this
* @since 2.0
*/
public ToStringBuilder appendAsObjectToString(Object object) {
- ObjectUtils.appendIdentityToString(this.getStringBuffer(), object);
+ ObjectUtils.identityToString(this.getStringBuffer(), object);
return this;
}
@@ -1036,6 +1016,16 @@
}
/**
+ * Returns the Object
being output.
+ *
+ * @return The object being output.
+ * @since 2.0
+ */
+ public Object getObject() {
+ return object;
+ }
+
+ /**
* Gets the StringBuffer
being populated.
*
* @return the StringBuffer
being populated
@@ -1062,21 +1052,17 @@
* This method appends the end of data indicator, and can only be called once.
* Use {@link #getStringBuffer} to get the current string state.
*
+ * If the object is null
, return the style's nullText
+ *
* @return the String toString
*/
public String toString() {
- style.appendEnd(buffer, object);
- return buffer.toString();
+ if (this.getObject() == null) {
+ this.getStringBuffer().append(this.getStyle().getNullText());
+ } else {
+ style.appendEnd(this.getStringBuffer(), this.getObject());
+ }
+ return this.getStringBuffer().toString();
}
- /**
- * Returns the Object
being output.
- *
- * @return The object being output.
- * @since 2.0
- */
- public Object getObject() {
- return object;
- }
-
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/ToStringStyle.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/ToStringStyle.java (.../ToStringStyle.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/ToStringStyle.java (.../ToStringStyle.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,62 +1,26 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
*
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+ * 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.
*/
package org.apache.commons.lang.builder;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;
+import java.util.WeakHashMap;
import org.apache.commons.lang.ClassUtils;
import org.apache.commons.lang.ObjectUtils;
@@ -82,43 +46,181 @@
* output the whole array, whereas the summary method will just output
* the array length.
*
- * @author Stephen Colebourne
+ * If you want to format the output of certain objects, such as dates, you
+ * must create a subclass and override a method.
+ *
+ * public class MyStyle extends ToStringStyle {
+ * protected void appendDetail(StringBuffer buffer, String fieldName, Object value) {
+ * if (value instanceof Date) {
+ * value = new SimpleDateFormat("yyyy-MM-dd").format(value);
+ * }
+ * buffer.append(value);
+ * }
+ * }
+ *
+ *
+ *
+ * @author Apache Software Foundation
* @author Gary Gregory
* @author Pete Gieser
+ * @author Masato Tezuka
* @since 1.0
* @version $Id$
*/
public abstract class ToStringStyle implements Serializable {
/**
- * The default toString style.
+ * The default toString style. Using the Using the Person
+ * example from {@link ToStringBuilder}, the output would look like this:
+ *
+ *
+ * Person@182f0db[name=John Doe,age=33,smoker=false]
+ *
*/
public static final ToStringStyle DEFAULT_STYLE = new DefaultToStringStyle();
+
/**
- * The multi line toString style.
+ * The multi line toString style. Using the Using the Person
+ * example from {@link ToStringBuilder}, the output would look like this:
+ *
+ *
+ * Person@182f0db[
+ * name=John Doe
+ * age=33
+ * smoker=false
+ * ]
+ *
*/
public static final ToStringStyle MULTI_LINE_STYLE = new MultiLineToStringStyle();
+
/**
- * The no field names toString style.
+ * The no field names toString style. Using the Using the
+ * Person
example from {@link ToStringBuilder}, the output
+ * would look like this:
+ *
+ *
+ * Person@182f0db[John Doe,33,false]
+ *
*/
public static final ToStringStyle NO_FIELD_NAMES_STYLE = new NoFieldNameToStringStyle();
+
/**
- * The simple toString style.
+ * The short prefix toString style. Using the Person
example
+ * from {@link ToStringBuilder}, the output would look like this:
+ *
+ *
+ * Person[name=John Doe,age=33,smoker=false]
+ *
+ *
+ * @since 2.1
*/
+ public static final ToStringStyle SHORT_PREFIX_STYLE = new ShortPrefixToStringStyle();
+
+ /**
+ * The simple toString style. Using the Using the Person
+ * example from {@link ToStringBuilder}, the output would look like this:
+ *
+ *
+ * John Doe,33,false
+ *
+ */
public static final ToStringStyle SIMPLE_STYLE = new SimpleToStringStyle();
/**
+ *
+ * A registry of objects used by reflectionToString
methods
+ * to detect cyclical object references and avoid infinite loops.
+ *
+ */
+ private static final ThreadLocal REGISTRY = new ThreadLocal();
+
+ /**
+ *
+ * Returns the registry of objects being traversed by the reflectionToString
+ * methods in the current thread.
+ *
+ *
+ * @return Set the registry of objects being traversed
+ */
+ static Map getRegistry() {
+ return (Map) REGISTRY.get();
+ }
+
+ /**
+ *
+ * Returns true
if the registry contains the given object.
+ * Used by the reflection methods to avoid infinite loops.
+ *
+ *
+ * @param value
+ * The object to lookup in the registry.
+ * @return boolean true
if the registry contains the given
+ * object.
+ */
+ static boolean isRegistered(Object value) {
+ Map m = getRegistry();
+ return m != null && m.containsKey(value);
+ }
+
+ /**
+ *
+ * Registers the given object. Used by the reflection methods to avoid
+ * infinite loops.
+ *
+ *
+ * @param value
+ * The object to register.
+ */
+ static void register(Object value) {
+ if (value != null) {
+ Map m = getRegistry();
+ if (m == null) {
+ m = new WeakHashMap();
+ REGISTRY.set(m);
+ }
+ m.put(value, null);
+ }
+ }
+
+ /**
+ *
+ * Unregisters the given object.
+ *
+ *
+ *
+ * Used by the reflection methods to avoid infinite loops.
+ *
+ *
+ * @param value
+ * The object to unregister.
+ */
+ static void unregister(Object value) {
+ if (value != null) {
+ Map m = getRegistry();
+ if (m != null) {
+ m.remove(value);
+ if (m.isEmpty()) {
+ REGISTRY.set(null);
+ }
+ }
+ }
+ }
+
+ /**
* Whether to use the field names, the default is true
.
*/
private boolean useFieldNames = true;
+
/**
* Whether to use the class name, the default is true
.
*/
private boolean useClassName = true;
+
/**
* Whether to use short class names, the default is false
.
*/
private boolean useShortClassName = false;
+
/**
* Whether to use the identity hash code, the default is true
.
*/
@@ -128,63 +230,78 @@
* The content start '['
.
*/
private String contentStart = "[";
+
/**
* The content end ']'
.
*/
private String contentEnd = "]";
+
/**
* The field name value separator '='
.
*/
private String fieldNameValueSeparator = "=";
+
/**
* Whether the field separator should be added before any other fields.
*/
private boolean fieldSeparatorAtStart = false;
+
/**
* Whether the field separator should be added after any other fields.
*/
private boolean fieldSeparatorAtEnd = false;
+
/**
* The field separator ','
.
*/
private String fieldSeparator = ",";
+
/**
* The array start '{'
.
*/
private String arrayStart = "{";
+
/**
* The array separator ','
.
*/
private String arraySeparator = ",";
+
/**
* The detail for array content.
*/
private boolean arrayContentDetail = true;
+
/**
* The array end '}'
.
*/
private String arrayEnd = "}";
+
/**
* The value to use when fullDetail is null
,
* the default value is true
.
*/
private boolean defaultFullDetail = true;
+
/**
* The null
text '<null>'
.
*/
private String nullText = "";
+
/**
* The summary size text start '.
*/
private String sizeStartText = "'>'
.
*/
private String sizeEndText = ">";
+
/**
* The summary object text start '<'
.
*/
private String summaryObjectStartText = "<";
+
/**
* The summary object text start '>'
.
*/
@@ -203,9 +320,10 @@
/**
* Append to the toString
the superclass toString.
- *
+ * NOTE: It assumes that the toString has been created from the same ToStringStyle.
+ *
* A null
superToString
is ignored.
- *
+ *
* @param buffer the StringBuffer
to populate
* @param superToString the super.toString()
* @since 2.0
@@ -216,9 +334,10 @@
/**
* Append to the toString
another toString.
- *
+ * NOTE: It assumes that the toString has been created from the same ToStringStyle.
+ *
* A null
toString
is ignored.
- *
+ *
* @param buffer the StringBuffer
to populate
* @param toString the additional toString
* @since 2.0
@@ -240,37 +359,39 @@
/**
* Append to the toString
the start of data indicator.
- *
+ *
* @param buffer the StringBuffer
to populate
- * @param object the Object
to build a
- * toString
for, must not be null
+ * @param object the Object
to build a toString
for
*/
public void appendStart(StringBuffer buffer, Object object) {
- appendClassName(buffer, object);
- appendIdentityHashCode(buffer, object);
- appendContentStart(buffer);
- if (fieldSeparatorAtStart) {
- appendFieldSeparator(buffer);
+ if (object != null) {
+ appendClassName(buffer, object);
+ appendIdentityHashCode(buffer, object);
+ appendContentStart(buffer);
+ if (fieldSeparatorAtStart) {
+ appendFieldSeparator(buffer);
+ }
}
}
/**
* Append to the toString
the end of data indicator.
- *
+ *
* @param buffer the StringBuffer
to populate
* @param object the Object
to build a
- * toString
for, must not be null
+ * toString
for.
*/
public void appendEnd(StringBuffer buffer, Object object) {
- if (fieldSeparatorAtEnd == false) {
+ if (this.fieldSeparatorAtEnd == false) {
removeLastFieldSeparator(buffer);
}
appendContentEnd(buffer);
+ unregister(object);
}
/**
* Remove the last field separator from the buffer.
- *
+ *
* @param buffer the StringBuffer
to populate
* @since 2.0
*/
@@ -337,98 +458,122 @@
* @param detail output detail or not
*/
protected void appendInternal(StringBuffer buffer, String fieldName, Object value, boolean detail) {
- if (ReflectionToStringBuilder.isRegistered(value)
+ if (isRegistered(value)
&& !(value instanceof Number || value instanceof Boolean || value instanceof Character)) {
- ObjectUtils.appendIdentityToString(buffer, value);
+ appendCyclicObject(buffer, fieldName, value);
+ return;
+ }
- } else if (value instanceof Collection) {
- if (detail) {
- appendDetail(buffer, fieldName, (Collection) value);
- } else {
- appendSummarySize(buffer, fieldName, ((Collection) value).size());
- }
+ register(value);
- } else if (value instanceof Map) {
- if (detail) {
- appendDetail(buffer, fieldName, (Map) value);
- } else {
- appendSummarySize(buffer, fieldName, ((Map) value).size());
- }
+ try {
+ if (value instanceof Collection) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (Collection) value);
+ } else {
+ appendSummarySize(buffer, fieldName, ((Collection) value).size());
+ }
- } else if (value instanceof long[]) {
- if (detail) {
- appendDetail(buffer, fieldName, (long[]) value);
- } else {
- appendSummary(buffer, fieldName, (long[]) value);
- }
+ } else if (value instanceof Map) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (Map) value);
+ } else {
+ appendSummarySize(buffer, fieldName, ((Map) value).size());
+ }
- } else if (value instanceof int[]) {
- if (detail) {
- appendDetail(buffer, fieldName, (int[]) value);
- } else {
- appendSummary(buffer, fieldName, (int[]) value);
- }
+ } else if (value instanceof long[]) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (long[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (long[]) value);
+ }
- } else if (value instanceof short[]) {
- if (detail) {
- appendDetail(buffer, fieldName, (short[]) value);
- } else {
- appendSummary(buffer, fieldName, (short[]) value);
- }
+ } else if (value instanceof int[]) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (int[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (int[]) value);
+ }
- } else if (value instanceof byte[]) {
- if (detail) {
- appendDetail(buffer, fieldName, (byte[]) value);
- } else {
- appendSummary(buffer, fieldName, (byte[]) value);
- }
+ } else if (value instanceof short[]) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (short[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (short[]) value);
+ }
- } else if (value instanceof char[]) {
- if (detail) {
- appendDetail(buffer, fieldName, (char[]) value);
- } else {
- appendSummary(buffer, fieldName, (char[]) value);
- }
+ } else if (value instanceof byte[]) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (byte[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (byte[]) value);
+ }
- } else if (value instanceof double[]) {
- if (detail) {
- appendDetail(buffer, fieldName, (double[]) value);
- } else {
- appendSummary(buffer, fieldName, (double[]) value);
- }
+ } else if (value instanceof char[]) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (char[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (char[]) value);
+ }
- } else if (value instanceof float[]) {
- if (detail) {
- appendDetail(buffer, fieldName, (float[]) value);
- } else {
- appendSummary(buffer, fieldName, (float[]) value);
- }
+ } else if (value instanceof double[]) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (double[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (double[]) value);
+ }
- } else if (value instanceof boolean[]) {
- if (detail) {
- appendDetail(buffer, fieldName, (boolean[]) value);
- } else {
- appendSummary(buffer, fieldName, (boolean[]) value);
- }
+ } else if (value instanceof float[]) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (float[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (float[]) value);
+ }
- } else if (value.getClass().isArray()) {
- if (detail) {
- appendDetail(buffer, fieldName, (Object[]) value);
- } else {
- appendSummary(buffer, fieldName, (Object[]) value);
- }
+ } else if (value instanceof boolean[]) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (boolean[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (boolean[]) value);
+ }
- } else {
- if (detail) {
- appendDetail(buffer, fieldName, value);
+ } else if (value.getClass().isArray()) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (Object[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (Object[]) value);
+ }
+
} else {
- appendSummary(buffer, fieldName, value);
+ if (detail) {
+ appendDetail(buffer, fieldName, value);
+ } else {
+ appendSummary(buffer, fieldName, value);
+ }
}
+ } finally {
+ unregister(value);
}
}
/**
* Append to the toString
an Object
+ * value that has been detected to participate in a cycle. This
+ * implementation will print the standard string value of the value.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param value the value to add to the toString
,
+ * not null
+ *
+ * @since 2.2
+ */
+ protected void appendCyclicObject(StringBuffer buffer, String fieldName, Object value) {
+ ObjectUtils.identityToString(buffer, value);
+ }
+
+ /**
+ * Append to the toString
an Object
* value, printing the full detail of the Object
.
*
* @param buffer the StringBuffer
to populate
@@ -1289,12 +1434,13 @@
/**
* Append to the toString
the class name.
- *
+ *
* @param buffer the StringBuffer
to populate
* @param object the Object
whose name to output
*/
protected void appendClassName(StringBuffer buffer, Object object) {
- if (useClassName) {
+ if (useClassName && object != null) {
+ register(object);
if (useShortClassName) {
buffer.append(getShortClassName(object.getClass()));
} else {
@@ -1305,20 +1451,21 @@
/**
* Append the {@link System#identityHashCode(java.lang.Object)}.
- *
+ *
* @param buffer the StringBuffer
to populate
* @param object the Object
whose id to output
*/
protected void appendIdentityHashCode(StringBuffer buffer, Object object) {
- if (useIdentityHashCode) {
+ if (this.isUseIdentityHashCode() && object!=null) {
+ register(object);
buffer.append('@');
buffer.append(Integer.toHexString(System.identityHashCode(object)));
}
}
/**
* Append to the toString
the content start.
- *
+ *
* @param buffer the StringBuffer
to populate
*/
protected void appendContentStart(StringBuffer buffer) {
@@ -1327,7 +1474,7 @@
/**
* Append to the toString
the content end.
- *
+ *
* @param buffer the StringBuffer
to populate
*/
protected void appendContentEnd(StringBuffer buffer) {
@@ -1338,7 +1485,7 @@
* Append to the toString
an indicator for null
.
*
* The default indicator is '<null>'
.
- *
+ *
* @param buffer the StringBuffer
to populate
* @param fieldName the field name, typically not used as already appended
*/
@@ -1348,7 +1495,7 @@
/**
* Append to the toString
the field separator.
- *
+ *
* @param buffer the StringBuffer
to populate
*/
protected void appendFieldSeparator(StringBuffer buffer) {
@@ -1357,7 +1504,7 @@
/**
* Append to the toString
the field start.
- *
+ *
* @param buffer the StringBuffer
to populate
* @param fieldName the field name
*/
@@ -1370,7 +1517,7 @@
/**
* Append to the toString the field end.
- *
+ *
* @param buffer the StringBuffer
to populate
* @param fieldName the field name, typically not used as already appended
*/
@@ -1409,7 +1556,7 @@
* null
indicating that it doesn't care about
* the detail level. In this case the default detail level is
* used.
- *
+ *
* @param fullDetailRequest the detail level requested
* @return whether full detail is to be shown
*/
@@ -1628,8 +1775,8 @@
* @param arrayEnd the new array end text
*/
protected void setArrayEnd(String arrayEnd) {
- if (arrayStart == null) {
- arrayStart = "";
+ if (arrayEnd == null) {
+ arrayEnd = "";
}
this.arrayEnd = arrayEnd;
}
@@ -1767,9 +1914,9 @@
//---------------------------------------------------------------------
/**
- * Gets whether the field separator should be added at the start
+ *
Gets whether the field separator should be added at the start
* of each buffer.
- *
+ *
* @return the fieldSeparatorAtStart flag
* @since 2.0
*/
@@ -1778,9 +1925,9 @@
}
/**
- * Sets whether the field separator should be added at the start
+ *
Sets whether the field separator should be added at the start
* of each buffer.
- *
+ *
* @param fieldSeparatorAtStart the fieldSeparatorAtStart flag
* @since 2.0
*/
@@ -1791,9 +1938,9 @@
//---------------------------------------------------------------------
/**
- * Gets whether the field separator should be added at the end
+ *
Gets whether the field separator should be added at the end
* of each buffer.
- *
+ *
* @return fieldSeparatorAtEnd flag
* @since 2.0
*/
@@ -1802,9 +1949,9 @@
}
/**
- * Sets whether the field separator should be added at the end
+ *
Sets whether the field separator should be added at the end
* of each buffer.
- *
+ *
* @param fieldSeparatorAtEnd the fieldSeparatorAtEnd flag
* @since 2.0
*/
@@ -1977,11 +2124,18 @@
private static final class DefaultToStringStyle extends ToStringStyle {
/**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
* Constructor.
*
* Use the static constant rather than instantiating.
*/
- private DefaultToStringStyle() {
+ DefaultToStringStyle() {
super();
}
@@ -2007,12 +2161,14 @@
*/
private static final class NoFieldNameToStringStyle extends ToStringStyle {
+ private static final long serialVersionUID = 1L;
+
/**
* Constructor.
*
* Use the static constant rather than instantiating.
*/
- private NoFieldNameToStringStyle() {
+ NoFieldNameToStringStyle() {
super();
this.setUseFieldNames(false);
}
@@ -2031,6 +2187,38 @@
//----------------------------------------------------------------------------
/**
+ * ToStringStyle
that prints out the short
+ * class name and no identity hashcode.
+ *
+ * This is an inner class rather than using
+ * StandardToStringStyle
to ensure its immutability.
+ */
+ private static final class ShortPrefixToStringStyle extends ToStringStyle {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor.
+ *
+ * Use the static constant rather than instantiating.
+ */
+ ShortPrefixToStringStyle() {
+ super();
+ this.setUseShortClassName(true);
+ this.setUseIdentityHashCode(false);
+ }
+
+ /**
+ * Ensure Singleton after serialization.
+ * @return the singleton
+ */
+ private Object readResolve() {
+ return ToStringStyle.SHORT_PREFIX_STYLE;
+ }
+
+ }
+
+ /**
* ToStringStyle
that does not print out the
* classname, identity hashcode, content start or field name.
*
@@ -2039,12 +2227,14 @@
*/
private static final class SimpleToStringStyle extends ToStringStyle {
+ private static final long serialVersionUID = 1L;
+
/**
* Constructor.
*
* Use the static constant rather than instantiating.
*/
- private SimpleToStringStyle() {
+ SimpleToStringStyle() {
super();
this.setUseClassName(false);
this.setUseIdentityHashCode(false);
@@ -2073,12 +2263,14 @@
*/
private static final class MultiLineToStringStyle extends ToStringStyle {
+ private static final long serialVersionUID = 1L;
+
/**
* Constructor.
*
* Use the static constant rather than instantiating.
*/
- private MultiLineToStringStyle() {
+ MultiLineToStringStyle() {
super();
this.setContentStart("[");
this.setFieldSeparator(SystemUtils.LINE_SEPARATOR + " ");
@@ -2097,73 +2289,4 @@
}
- //----------------------------------------------------------------------------
-
-// Removed, as the XML style needs more work for escaping characters, arrays,
-// collections, maps and embedded beans.
-// /**
-// * ToStringStyle that outputs in XML style
-// */
-// private static class XMLToStringStyle extends ToStringStyle {
-//
-// /**
-// * Constructor - use the static constant rather than instantiating.
-// */
-// private XMLToStringStyle() {
-// super();
-// nullText = "null";
-// sizeStartText = "size=";
-// sizeEndText = "";
-// }
-//
-// /**
-// * @see ToStringStyle#appendStart(StringBuffer, Object)
-// */
-// public void appendStart(StringBuffer buffer, Object object) {
-// buffer.append('<');
-// buffer.append(getShortClassName(object.getClass()));
-// buffer.append(" class=\"");
-// appendClassName(buffer, object);
-// buffer.append("\" hashCode=\"");
-// appendIdentityHashCode(buffer, object);
-// buffer.append("\">");
-// buffer.append(SystemUtils.LINE_SEPARATOR);
-// buffer.append(" ");
-// }
-//
-// /**
-// * @see ToStringStyle#appendFieldStart(StringBuffer, String)
-// */
-// protected void appendFieldStart(StringBuffer buffer, String fieldName) {
-// buffer.append('<');
-// buffer.append(fieldName);
-// buffer.append('>');
-// }
-//
-// /**
-// * @see ToStringStyle#appendFieldEnd(StringBuffer, String)
-// */
-// protected void appendFieldEnd(StringBuffer buffer, String fieldName) {
-// buffer.append("");
-// buffer.append(fieldName);
-// buffer.append('>');
-// buffer.append(SystemUtils.LINE_SEPARATOR);
-// buffer.append(" ");
-// }
-//
-// /**
-// * @see ToStringStyle#appendEnd(StringBuffer, Object)
-// */
-// public void appendEnd(StringBuffer buffer, Object object) {
-// int len = buffer.length();
-// if (len > 2 && buffer.charAt(len - 1) == ' ' && buffer.charAt(len - 2) == ' ') {
-// buffer.setLength(len - 2);
-// }
-// buffer.append("");
-// buffer.append(getShortClassName(object.getClass()));
-// buffer.append("\">");
-// }
-//
-// }
-
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/package.html
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/package.html (.../package.html) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/package.html (.../package.html) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,7 +1,28 @@
+
Assists in creating consistent equals(Object)
, toString()
,
hashCode()
, and compareTo(Object)
methods.
+@see java.lang.Object#equals(Object)
+@see java.lang.Object#toString()
+@see java.lang.Object#hashCode()
+@see java.lang.Comparable#compareTo(Object)
@since 1.0
+These classes are not thread-safe.
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/enum/Enum.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/enum/Enum.java (.../Enum.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/enum/Enum.java (.../Enum.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,55 +1,18 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang.enum;
@@ -62,6 +25,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.WeakHashMap;
import org.apache.commons.lang.ClassUtils;
import org.apache.commons.lang.StringUtils;
@@ -172,7 +136,7 @@
* super("Plus");
* }
* public int eval(int a, int b) {
- * return (a + b);
+ * return a + b;
* }
* }
* public static final OperationEnum MINUS = new MinusOperation();
@@ -181,7 +145,7 @@
* super("Minus");
* }
* public int eval(int a, int b) {
- * return (a - b);
+ * return a - b;
* }
* }
*
@@ -214,17 +178,72 @@
*
* The code above will work on JDK 1.2. If JDK1.3 and later is used,
* the subclasses may be defined as anonymous.
+ *
+ * Nested class Enums
*
+ * Care must be taken with class loading when defining a static nested class
+ * for enums. The static nested class can be loaded without the surrounding outer
+ * class being loaded. This can result in an empty list/map/iterator being returned.
+ * One solution is to define a static block that references the outer class where
+ * the constants are defined. For example:
+ *
+ *
+ * public final class Outer {
+ * public static final BWEnum BLACK = new BWEnum("Black");
+ * public static final BWEnum WHITE = new BWEnum("White");
+ *
+ * // static nested enum class
+ * public static final class BWEnum extends Enum {
+ *
+ * static {
+ * // explicitly reference BWEnum class to force constants to load
+ * Object obj = Outer.BLACK;
+ * }
+ *
+ * // ... other methods omitted
+ * }
+ * }
+ *
+ *
+ * Although the above solves the problem, it is not recommended. The best solution
+ * is to define the constants in the enum class, and hold references in the outer class:
+ *
+ *
+ * public final class Outer {
+ * public static final BWEnum BLACK = BWEnum.BLACK;
+ * public static final BWEnum WHITE = BWEnum.WHITE;
+ *
+ * // static nested enum class
+ * public static final class BWEnum extends Enum {
+ * // only define constants in enum classes - private if desired
+ * private static final BWEnum BLACK = new BWEnum("Black");
+ * private static final BWEnum WHITE = new BWEnum("White");
+ *
+ * // ... other methods omitted
+ * }
+ * }
+ *
+ *
+ * For more details, see the 'Nested' test cases.
+ *
+ * @deprecated Replaced by {@link org.apache.commons.lang.enums.Enum org.apache.commons.lang.enums.Enum}
+ * and will be removed in version 3.0. All classes in this package are deprecated and repackaged to
+ * {@link org.apache.commons.lang.enums} since enum
is a Java 1.5 keyword.
+ * @see org.apache.commons.lang.enums.Enum
* @author Apache Avalon project
- * @author Stephen Colebourne
+ * @author Apache Software Foundation
* @author Chris Webb
* @author Mike Bowler
* @since 1.0
* @version $Id$
*/
public abstract class Enum implements Comparable, Serializable {
- /** Lang version 1.0.1 serial compatability */
+ /**
+ * Required for serialization support. Lang version 1.0.1 serial compatibility.
+ *
+ * @see java.io.Serializable
+ */
private static final long serialVersionUID = -487045951170455942L;
// After discussion, the default size for HashMaps is used, as the
@@ -237,7 +256,11 @@
/**
* Map
, key of class name, value of Entry
.
*/
- private static final Map cEnumClasses = new HashMap();
+ private static Map cEnumClasses
+ // LANG-334: To avoid exposing a mutating map,
+ // we copy it each time we add to it. This is cheaper than
+ // using a synchronized map since we are almost entirely reads
+ = new WeakHashMap();
/**
* The string representation of the Enum.
@@ -279,7 +302,8 @@
/**
*
Restrictive constructor.
*/
- private Entry() {
+ protected Entry() {
+ super();
}
}
@@ -329,12 +353,18 @@
if (ok == false) {
throw new IllegalArgumentException("getEnumClass() must return a superclass of this class");
}
-
- // create entry
- Entry entry = (Entry) cEnumClasses.get(enumClass);
- if (entry == null) {
- entry = createEntry(enumClass);
- cEnumClasses.put(enumClass, entry);
+
+ Entry entry;
+ synchronized( Enum.class ) { // LANG-334
+ // create entry
+ entry = (Entry) cEnumClasses.get(enumClass);
+ if (entry == null) {
+ entry = createEntry(enumClass);
+ Map myMap = new WeakHashMap( ); // we avoid the (Map) constructor to achieve JDK 1.2 support
+ myMap.putAll( cEnumClasses );
+ myMap.put(enumClass, entry);
+ cEnumClasses = myMap;
+ }
}
if (entry.map.containsKey(name)) {
throw new IllegalArgumentException("The Enum name must be unique, '" + name + "' has already been added");
@@ -354,7 +384,7 @@
if (entry == null) {
return null;
}
- return (Enum) entry.map.get(getName());
+ return entry.map.get(getName());
}
//--------------------------------------------------------------------------------
@@ -366,7 +396,7 @@
* be null
* @param name the name of the Enum
to get,
* may be null
- * @return the enum object, or null if the enum does not exist
+ * @return the enum object, or null
if the enum does not exist
* @throws IllegalArgumentException if the enum class
* is null
*/
@@ -454,6 +484,17 @@
throw new IllegalArgumentException("The Class must be a subclass of Enum");
}
Entry entry = (Entry) cEnumClasses.get(enumClass);
+
+ if (entry == null) {
+ try {
+ // LANG-76 - try to force class initialization for JDK 1.5+
+ Class.forName(enumClass.getName(), true, enumClass.getClassLoader());
+ entry = (Entry) cEnumClasses.get(enumClass);
+ } catch (Exception e) {
+ // Ignore
+ }
+ }
+
return entry;
}
@@ -510,6 +551,9 @@
* Two Enum objects are considered equal
* if they have the same class names and the same names.
* Identity is tested for first, so this method usually runs fast.
+ *
+ * If the parameter is in a different class loader than this instance,
+ * reflection is used to compare the names.
*
* @param other the other object to compare for equality
* @return true
if the Enums are equal
@@ -520,34 +564,19 @@
} else if (other == null) {
return false;
} else if (other.getClass() == this.getClass()) {
- // shouldn't happen, but...
+ // Ok to do a class cast to Enum here since the test above
+ // guarantee both
+ // classes are in the same class loader.
return iName.equals(((Enum) other).iName);
- } else if (((Enum) other).getEnumClass().getName().equals(getEnumClass().getName())) {
- // different classloaders
- try {
- // try to avoid reflection
- return iName.equals(((Enum) other).iName);
-
- } catch (ClassCastException ex) {
- // use reflection
- try {
- Method mth = other.getClass().getMethod("getName", null);
- String name = (String) mth.invoke(other, null);
- return iName.equals(name);
- } catch (NoSuchMethodException ex2) {
- // ignore - should never happen
- } catch (IllegalAccessException ex2) {
- // ignore - should never happen
- } catch (InvocationTargetException ex2) {
- // ignore - should never happen
- }
+ } else {
+ // This and other are in different class loaders, we must check indirectly
+ if (other.getClass().getName().equals(this.getClass().getName()) == false) {
return false;
}
- } else {
- return false;
+ return iName.equals( getNameInOtherClassLoader(other) );
}
}
-
+
/**
* Returns a suitable hashCode for the enumeration.
*
@@ -563,6 +592,9 @@
* The default ordering is alphabetic by name, but this
* can be overridden by subclasses.
*
+ * If the parameter is in a different class loader than this instance,
+ * reflection is used to compare the names.
+ *
* @see java.lang.Comparable#compareTo(Object)
* @param other the other object to compare to
* @return -ve if this is less than the other object, +ve if greater
@@ -574,10 +606,38 @@
if (other == this) {
return 0;
}
+ if (other.getClass() != this.getClass()) {
+ if (other.getClass().getName().equals(this.getClass().getName())) {
+ return iName.compareTo( getNameInOtherClassLoader(other) );
+ }
+ throw new ClassCastException(
+ "Different enum class '" + ClassUtils.getShortClassName(other.getClass()) + "'");
+ }
return iName.compareTo(((Enum) other).iName);
}
/**
+ * Use reflection to return an objects class name.
+ *
+ * @param other The object to determine the class name for
+ * @return The class name
+ */
+ private String getNameInOtherClassLoader(Object other) {
+ try {
+ Method mth = other.getClass().getMethod("getName", null);
+ String name = (String) mth.invoke(other, null);
+ return name;
+ } catch (NoSuchMethodException e) {
+ // ignore - should never happen
+ } catch (IllegalAccessException e) {
+ // ignore - should never happen
+ } catch (InvocationTargetException e) {
+ // ignore - should never happen
+ }
+ throw new IllegalStateException("This should not happen");
+ }
+
+ /**
* Human readable description of this Enum item.
*
* @return String in the form type[name]
, for example:
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/enum/EnumUtils.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/enum/EnumUtils.java (.../EnumUtils.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/enum/EnumUtils.java (.../EnumUtils.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,55 +1,18 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang.enum;
@@ -60,9 +23,13 @@
/**
* Utility class for accessing and manipulating {@link Enum}s.
*
+ * @deprecated Replaced by {@link org.apache.commons.lang.enums.EnumUtils org.apache.commons.lang.enums.EnumUtils}
+ * and will be removed in version 3.0. All classes in this package are deprecated and repackaged to
+ * {@link org.apache.commons.lang.enums} since enum
is a Java 1.5 keyword.
+ * @see org.apache.commons.lang.enums.EnumUtils
* @see Enum
* @see ValuedEnum
- * @author Stephen Colebourne
+ * @author Apache Software Foundation
* @author Gary Gregory
* @since 1.0
* @version $Id$
@@ -74,6 +41,7 @@
* @since 2.0
*/
public EnumUtils() {
+ super();
}
/**
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/enum/ValuedEnum.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/enum/ValuedEnum.java (.../ValuedEnum.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/enum/ValuedEnum.java (.../ValuedEnum.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,55 +1,18 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang.enum;
@@ -110,7 +73,7 @@
* The above class could then be used as follows:
*
*
- * public void doSomething(JavaVersion ver) {
+ * public void doSomething(JavaVersionEnum ver) {
* switch (ver.getValue()) {
* case JAVA1_0_VALUE:
* // ...
@@ -130,14 +93,22 @@
* Unfortunately, Java restrictions require these to be coded as shown in each subclass.
* An alternative choice is to use the {@link EnumUtils} class.
*
+ * @deprecated Replaced by {@link org.apache.commons.lang.enums.ValuedEnum org.apache.commons.lang.enums.ValuedEnum}
+ * and will be removed in version 3.0. All classes in this package are deprecated and repackaged to
+ * {@link org.apache.commons.lang.enums} since enum
is a Java 1.5 keyword.
+ * @see org.apache.commons.lang.enums.ValuedEnum
* @author Apache Avalon project
- * @author Stephen Colebourne
+ * @author Apache Software Foundation
* @since 1.0
* @version $Id$
*/
public abstract class ValuedEnum extends Enum {
- /** Lang version 1.0.1 serial compatability */
+ /**
+ * Required for serialization support. Lang version 1.0.1 serial compatibility.
+ *
+ * @see java.io.Serializable
+ */
private static final long serialVersionUID = -7129650521543789085L;
/**
@@ -174,9 +145,9 @@
}
List list = Enum.getEnumList(enumClass);
for (Iterator it = list.iterator(); it.hasNext();) {
- ValuedEnum enum = (ValuedEnum) it.next();
- if (enum.getValue() == value) {
- return enum;
+ ValuedEnum enumeration = (ValuedEnum) it.next();
+ if (enumeration.getValue() == value) {
+ return enumeration;
}
}
return null;
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/enum/package.html
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/enum/package.html (.../package.html) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/enum/package.html (.../package.html) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,8 +1,35 @@
+
-Provides an implementation of the C style 'enum' in the Java world.
-
+
+Deprecated and replaced by {@link org.apache.commons.lang.enums}
+and will be removed in version 3.0.
+
+
+All classes in this package are deprecated and repackaged to {@link org.apache.commons.lang.enums}
+since enum
is a Java 1.5 keyword.
+
+
+Provides an implementation of the C style enum
in the Java world.
+
+
The classic example being an RGB color enumeration.
+
public final class ColorEnum extends Enum {
public static final ColorEnum RED = new ColorEnum("Red");
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/enums/Enum.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/enums/Enum.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/enums/Enum.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,701 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang.enums;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import org.apache.commons.lang.ClassUtils;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * Abstract superclass for type-safe enums.
+ *
+ * One feature of the C programming language lacking in Java is enumerations. The
+ * C implementation based on ints was poor and open to abuse. The original Java
+ * recommendation and most of the JDK also uses int constants. It has been recognised
+ * however that a more robust type-safe class-based solution can be designed. This
+ * class follows the basic Java type-safe enumeration pattern.
+ *
+ * NOTE: Due to the way in which Java ClassLoaders work, comparing
+ * Enum objects should always be done using equals()
, not ==
.
+ * The equals() method will try == first so in most cases the effect is the same.
+ *
+ * Of course, if you actually want (or don't mind) Enums in different class
+ * loaders being non-equal, then you can use ==
.
+ *
+ * Simple Enums
+ *
+ * To use this class, it must be subclassed. For example:
+ *
+ *
+ * public final class ColorEnum extends Enum {
+ * public static final ColorEnum RED = new ColorEnum("Red");
+ * public static final ColorEnum GREEN = new ColorEnum("Green");
+ * public static final ColorEnum BLUE = new ColorEnum("Blue");
+ *
+ * private ColorEnum(String color) {
+ * super(color);
+ * }
+ *
+ * public static ColorEnum getEnum(String color) {
+ * return (ColorEnum) getEnum(ColorEnum.class, color);
+ * }
+ *
+ * public static Map getEnumMap() {
+ * return getEnumMap(ColorEnum.class);
+ * }
+ *
+ * public static List getEnumList() {
+ * return getEnumList(ColorEnum.class);
+ * }
+ *
+ * public static Iterator iterator() {
+ * return iterator(ColorEnum.class);
+ * }
+ * }
+ *
+ *
+ * As shown, each enum has a name. This can be accessed using getName
.
+ *
+ * The getEnum
and iterator
methods are recommended.
+ * Unfortunately, Java restrictions require these to be coded as shown in each subclass.
+ * An alternative choice is to use the {@link EnumUtils} class.
+ *
+ * Subclassed Enums
+ * A hierarchy of Enum classes can be built. In this case, the superclass is
+ * unaffected by the addition of subclasses (as per normal Java). The subclasses
+ * may add additional Enum constants of the type of the superclass. The
+ * query methods on the subclass will return all of the Enum constants from the
+ * superclass and subclass.
+ *
+ *
+ * public final class ExtraColorEnum extends ColorEnum {
+ * // NOTE: Color enum declared above is final, change that to get this
+ * // example to compile.
+ * public static final ColorEnum YELLOW = new ExtraColorEnum("Yellow");
+ *
+ * private ExtraColorEnum(String color) {
+ * super(color);
+ * }
+ *
+ * public static ColorEnum getEnum(String color) {
+ * return (ColorEnum) getEnum(ExtraColorEnum.class, color);
+ * }
+ *
+ * public static Map getEnumMap() {
+ * return getEnumMap(ExtraColorEnum.class);
+ * }
+ *
+ * public static List getEnumList() {
+ * return getEnumList(ExtraColorEnum.class);
+ * }
+ *
+ * public static Iterator iterator() {
+ * return iterator(ExtraColorEnum.class);
+ * }
+ * }
+ *
+ *
+ * This example will return RED, GREEN, BLUE, YELLOW from the List and iterator
+ * methods in that order. The RED, GREEN and BLUE instances will be the same (==)
+ * as those from the superclass ColorEnum. Note that YELLOW is declared as a
+ * ColorEnum and not an ExtraColorEnum.
+ *
+ * Functional Enums
+ *
+ * The enums can have functionality by defining subclasses and
+ * overriding the getEnumClass()
method:
+ *
+ *
+ * public static final OperationEnum PLUS = new PlusOperation();
+ * private static final class PlusOperation extends OperationEnum {
+ * private PlusOperation() {
+ * super("Plus");
+ * }
+ * public int eval(int a, int b) {
+ * return a + b;
+ * }
+ * }
+ * public static final OperationEnum MINUS = new MinusOperation();
+ * private static final class MinusOperation extends OperationEnum {
+ * private MinusOperation() {
+ * super("Minus");
+ * }
+ * public int eval(int a, int b) {
+ * return a - b;
+ * }
+ * }
+ *
+ * private OperationEnum(String color) {
+ * super(color);
+ * }
+ *
+ * public final Class getEnumClass() { // NOTE: new method!
+ * return OperationEnum.class;
+ * }
+ *
+ * public abstract double eval(double a, double b);
+ *
+ * public static OperationEnum getEnum(String name) {
+ * return (OperationEnum) getEnum(OperationEnum.class, name);
+ * }
+ *
+ * public static Map getEnumMap() {
+ * return getEnumMap(OperationEnum.class);
+ * }
+ *
+ * public static List getEnumList() {
+ * return getEnumList(OperationEnum.class);
+ * }
+ *
+ * public static Iterator iterator() {
+ * return iterator(OperationEnum.class);
+ * }
+ * }
+ *
+ * The code above will work on JDK 1.2. If JDK1.3 and later is used,
+ * the subclasses may be defined as anonymous.
+ *
+ * Nested class Enums
+ *
+ * Care must be taken with class loading when defining a static nested class
+ * for enums. The static nested class can be loaded without the surrounding outer
+ * class being loaded. This can result in an empty list/map/iterator being returned.
+ * One solution is to define a static block that references the outer class where
+ * the constants are defined. For example:
+ *
+ *
+ * public final class Outer {
+ * public static final BWEnum BLACK = new BWEnum("Black");
+ * public static final BWEnum WHITE = new BWEnum("White");
+ *
+ * // static nested enum class
+ * public static final class BWEnum extends Enum {
+ *
+ * static {
+ * // explicitly reference BWEnum class to force constants to load
+ * Object obj = Outer.BLACK;
+ * }
+ *
+ * // ... other methods omitted
+ * }
+ * }
+ *
+ *
+ * Although the above solves the problem, it is not recommended. The best solution
+ * is to define the constants in the enum class, and hold references in the outer class:
+ *
+ *
+ * public final class Outer {
+ * public static final BWEnum BLACK = BWEnum.BLACK;
+ * public static final BWEnum WHITE = BWEnum.WHITE;
+ *
+ * // static nested enum class
+ * public static final class BWEnum extends Enum {
+ * // only define constants in enum classes - private if desired
+ * private static final BWEnum BLACK = new BWEnum("Black");
+ * private static final BWEnum WHITE = new BWEnum("White");
+ *
+ * // ... other methods omitted
+ * }
+ * }
+ *
+ *
+ * For more details, see the 'Nested' test cases.
+ *
+ *
Lang Enums and Java 5.0 Enums
+ *
+ * Enums were added to Java in Java 5.0. The main differences between Lang's
+ * implementation and the new official JDK implementation are:
+ *
+ * - The standard Enum is a not just a superclass, but is a type baked into the
+ * language.
+ * - The standard Enum does not support extension, so the standard methods that
+ * are provided in the Lang enum are not available.
+ * - Lang mandates a String name, whereas the standard Enum uses the class
+ * name as its name. getName() changes to name().
+ *
+ *
+ * Generally people should use the standard Enum. Migrating from the Lang
+ * enum to the standard Enum is not as easy as it might be due to the lack of
+ * class inheritence in standard Enums. This means that it's not possible
+ * to provide a 'super-enum' which could provide the same utility methods
+ * that the Lang enum does. The following utility class is a Java 5.0
+ * version of our EnumUtils class and provides those utility methods.
+ *
+ *
+ * import java.util.*;
+ *
+ * public class EnumUtils {
+ *
+ * public static Enum getEnum(Class enumClass, String token) {
+ * return Enum.valueOf(enumClass, token);
+ * }
+ *
+ * public static Map getEnumMap(Class enumClass) {
+ * HashMap map = new HashMap();
+ * Iterator itr = EnumUtils.iterator(enumClass);
+ * while(itr.hasNext()) {
+ * Enum enm = (Enum) itr.next();
+ * map.put( enm.name(), enm );
+ * }
+ * return map;
+ * }
+ *
+ * public static List getEnumList(Class enumClass) {
+ * return new ArrayList( EnumSet.allOf(enumClass) );
+ * }
+ *
+ * public static Iterator iterator(Class enumClass) {
+ * return EnumUtils.getEnumList(enumClass).iterator();
+ * }
+ * }
+ *
+ *
+ * @author Apache Avalon project
+ * @author Apache Software Foundation
+ * @author Chris Webb
+ * @author Mike Bowler
+ * @author Matthias Eichel
+ * @since 2.1 (class existed in enum package from v1.0)
+ * @version $Id$
+ */
+public abstract class Enum implements Comparable, Serializable {
+
+ /**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = -487045951170455942L;
+
+ // After discussion, the default size for HashMaps is used, as the
+ // sizing algorithm changes across the JDK versions
+ /**
+ * An empty Map
, as JDK1.2 didn't have an empty map.
+ */
+ private static final Map EMPTY_MAP = Collections.unmodifiableMap(new HashMap(0));
+
+ /**
+ * Map
, key of class name, value of Entry
.
+ */
+ private static Map cEnumClasses
+ // LANG-334: To avoid exposing a mutating map,
+ // we copy it each time we add to it. This is cheaper than
+ // using a synchronized map since we are almost entirely reads
+ = new WeakHashMap();
+
+ /**
+ * The string representation of the Enum.
+ */
+ private final String iName;
+
+ /**
+ * The hashcode representation of the Enum.
+ */
+ private transient final int iHashCode;
+
+ /**
+ * The toString representation of the Enum.
+ * @since 2.0
+ */
+ protected transient String iToString = null;
+
+ /**
+ * Enable the iterator to retain the source code order.
+ */
+ private static class Entry {
+ /**
+ * Map of Enum name to Enum.
+ */
+ final Map map = new HashMap();
+ /**
+ * Map of Enum name to Enum.
+ */
+ final Map unmodifiableMap = Collections.unmodifiableMap(map);
+ /**
+ * List of Enums in source code order.
+ */
+ final List list = new ArrayList(25);
+ /**
+ * Map of Enum name to Enum.
+ */
+ final List unmodifiableList = Collections.unmodifiableList(list);
+
+ /**
+ * Restrictive constructor.
+ */
+ protected Entry() {
+ super();
+ }
+ }
+
+ /**
+ * Constructor to add a new named item to the enumeration.
+ *
+ * @param name the name of the enum object,
+ * must not be empty or null
+ * @throws IllegalArgumentException if the name is null
+ * or an empty string
+ * @throws IllegalArgumentException if the getEnumClass() method returns
+ * a null or invalid Class
+ */
+ protected Enum(String name) {
+ super();
+ init(name);
+ iName = name;
+ iHashCode = 7 + getEnumClass().hashCode() + 3 * name.hashCode();
+ // cannot create toString here as subclasses may want to include other data
+ }
+
+ /**
+ * Initializes the enumeration.
+ *
+ * @param name the enum name
+ * @throws IllegalArgumentException if the name is null or empty or duplicate
+ * @throws IllegalArgumentException if the enumClass is null or invalid
+ */
+ private void init(String name) {
+ if (StringUtils.isEmpty(name)) {
+ throw new IllegalArgumentException("The Enum name must not be empty or null");
+ }
+
+ Class enumClass = getEnumClass();
+ if (enumClass == null) {
+ throw new IllegalArgumentException("getEnumClass() must not be null");
+ }
+ Class cls = getClass();
+ boolean ok = false;
+ while (cls != null && cls != Enum.class && cls != ValuedEnum.class) {
+ if (cls == enumClass) {
+ ok = true;
+ break;
+ }
+ cls = cls.getSuperclass();
+ }
+ if (ok == false) {
+ throw new IllegalArgumentException("getEnumClass() must return a superclass of this class");
+ }
+
+ Entry entry;
+ synchronized( Enum.class ) { // LANG-334
+ // create entry
+ entry = (Entry) cEnumClasses.get(enumClass);
+ if (entry == null) {
+ entry = createEntry(enumClass);
+ Map myMap = new WeakHashMap( ); // we avoid the (Map) constructor to achieve JDK 1.2 support
+ myMap.putAll( cEnumClasses );
+ myMap.put(enumClass, entry);
+ cEnumClasses = myMap;
+ }
+ }
+ if (entry.map.containsKey(name)) {
+ throw new IllegalArgumentException("The Enum name must be unique, '" + name + "' has already been added");
+ }
+ entry.map.put(name, this);
+ entry.list.add(this);
+ }
+
+ /**
+ * Handle the deserialization of the class to ensure that multiple
+ * copies are not wastefully created, or illegal enum types created.
+ *
+ * @return the resolved object
+ */
+ protected Object readResolve() {
+ Entry entry = (Entry) cEnumClasses.get(getEnumClass());
+ if (entry == null) {
+ return null;
+ }
+ return entry.map.get(getName());
+ }
+
+ //--------------------------------------------------------------------------------
+
+ /**
+ * Gets an Enum
object by class and name.
+ *
+ * @param enumClass the class of the Enum to get, must not
+ * be null
+ * @param name the name of the Enum
to get,
+ * may be null
+ * @return the enum object, or null
if the enum does not exist
+ * @throws IllegalArgumentException if the enum class
+ * is null
+ */
+ protected static Enum getEnum(Class enumClass, String name) {
+ Entry entry = getEntry(enumClass);
+ if (entry == null) {
+ return null;
+ }
+ return (Enum) entry.map.get(name);
+ }
+
+ /**
+ * Gets the Map
of Enum
objects by
+ * name using the Enum
class.
+ *
+ * If the requested class has no enum objects an empty
+ * Map
is returned.
+ *
+ * @param enumClass the class of the Enum
to get,
+ * must not be null
+ * @return the enum object Map
+ * @throws IllegalArgumentException if the enum class is null
+ * @throws IllegalArgumentException if the enum class is not a subclass of Enum
+ */
+ protected static Map getEnumMap(Class enumClass) {
+ Entry entry = getEntry(enumClass);
+ if (entry == null) {
+ return EMPTY_MAP;
+ }
+ return entry.unmodifiableMap;
+ }
+
+ /**
+ * Gets the List
of Enum
objects using the
+ * Enum
class.
+ *
+ * The list is in the order that the objects were created (source code order).
+ * If the requested class has no enum objects an empty List
is
+ * returned.
+ *
+ * @param enumClass the class of the Enum
to get,
+ * must not be null
+ * @return the enum object Map
+ * @throws IllegalArgumentException if the enum class is null
+ * @throws IllegalArgumentException if the enum class is not a subclass of Enum
+ */
+ protected static List getEnumList(Class enumClass) {
+ Entry entry = getEntry(enumClass);
+ if (entry == null) {
+ return Collections.EMPTY_LIST;
+ }
+ return entry.unmodifiableList;
+ }
+
+ /**
+ * Gets an Iterator
over the Enum
objects in
+ * an Enum
class.
+ *
+ * The Iterator
is in the order that the objects were
+ * created (source code order). If the requested class has no enum
+ * objects an empty Iterator
is returned.
+ *
+ * @param enumClass the class of the Enum
to get,
+ * must not be null
+ * @return an iterator of the Enum objects
+ * @throws IllegalArgumentException if the enum class is null
+ * @throws IllegalArgumentException if the enum class is not a subclass of Enum
+ */
+ protected static Iterator iterator(Class enumClass) {
+ return Enum.getEnumList(enumClass).iterator();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets an Entry
from the map of Enums.
+ *
+ * @param enumClass the class of the Enum
to get
+ * @return the enum entry
+ */
+ private static Entry getEntry(Class enumClass) {
+ if (enumClass == null) {
+ throw new IllegalArgumentException("The Enum Class must not be null");
+ }
+ if (Enum.class.isAssignableFrom(enumClass) == false) {
+ throw new IllegalArgumentException("The Class must be a subclass of Enum");
+ }
+ Entry entry = (Entry) cEnumClasses.get(enumClass);
+
+ if (entry == null) {
+ try {
+ // LANG-76 - try to force class initialization for JDK 1.5+
+ Class.forName(enumClass.getName(), true, enumClass.getClassLoader());
+ entry = (Entry) cEnumClasses.get(enumClass);
+ } catch (Exception e) {
+ // Ignore
+ }
+ }
+
+ return entry;
+ }
+
+ /**
+ * Creates an Entry
for storing the Enums.
+ *
+ * This accounts for subclassed Enums.
+ *
+ * @param enumClass the class of the Enum
to get
+ * @return the enum entry
+ */
+ private static Entry createEntry(Class enumClass) {
+ Entry entry = new Entry();
+ Class cls = enumClass.getSuperclass();
+ while (cls != null && cls != Enum.class && cls != ValuedEnum.class) {
+ Entry loopEntry = (Entry) cEnumClasses.get(cls);
+ if (loopEntry != null) {
+ entry.list.addAll(loopEntry.list);
+ entry.map.putAll(loopEntry.map);
+ break; // stop here, as this will already have had superclasses added
+ }
+ cls = cls.getSuperclass();
+ }
+ return entry;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Retrieve the name of this Enum item, set in the constructor.
+ *
+ * @return the String
name of this Enum item
+ */
+ public final String getName() {
+ return iName;
+ }
+
+ /**
+ * Retrieves the Class of this Enum item, set in the constructor.
+ *
+ * This is normally the same as getClass()
, but for
+ * advanced Enums may be different. If overridden, it must return a
+ * constant value.
+ *
+ * @return the Class
of the enum
+ * @since 2.0
+ */
+ public Class getEnumClass() {
+ return getClass();
+ }
+
+ /**
+ * Tests for equality.
+ *
+ * Two Enum objects are considered equal
+ * if they have the same class names and the same names.
+ * Identity is tested for first, so this method usually runs fast.
+ *
+ * If the parameter is in a different class loader than this instance,
+ * reflection is used to compare the names.
+ *
+ * @param other the other object to compare for equality
+ * @return true
if the Enums are equal
+ */
+ public final boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ } else if (other == null) {
+ return false;
+ } else if (other.getClass() == this.getClass()) {
+ // Ok to do a class cast to Enum here since the test above
+ // guarantee both
+ // classes are in the same class loader.
+ return iName.equals(((Enum) other).iName);
+ } else {
+ // This and other are in different class loaders, we must check indirectly
+ if (other.getClass().getName().equals(this.getClass().getName()) == false) {
+ return false;
+ }
+ return iName.equals( getNameInOtherClassLoader(other) );
+ }
+ }
+
+ /**
+ * Returns a suitable hashCode for the enumeration.
+ *
+ * @return a hashcode based on the name
+ */
+ public final int hashCode() {
+ return iHashCode;
+ }
+
+ /**
+ * Tests for order.
+ *
+ * The default ordering is alphabetic by name, but this
+ * can be overridden by subclasses.
+ *
+ * If the parameter is in a different class loader than this instance,
+ * reflection is used to compare the names.
+ *
+ * @see java.lang.Comparable#compareTo(Object)
+ * @param other the other object to compare to
+ * @return -ve if this is less than the other object, +ve if greater
+ * than, 0
of equal
+ * @throws ClassCastException if other is not an Enum
+ * @throws NullPointerException if other is null
+ */
+ public int compareTo(Object other) {
+ if (other == this) {
+ return 0;
+ }
+ if (other.getClass() != this.getClass()) {
+ if (other.getClass().getName().equals(this.getClass().getName())) {
+ return iName.compareTo( getNameInOtherClassLoader(other) );
+ }
+ throw new ClassCastException(
+ "Different enum class '" + ClassUtils.getShortClassName(other.getClass()) + "'");
+ }
+ return iName.compareTo(((Enum) other).iName);
+ }
+
+ /**
+ * Use reflection to return an objects class name.
+ *
+ * @param other The object to determine the class name for
+ * @return The class name
+ */
+ private String getNameInOtherClassLoader(Object other) {
+ try {
+ Method mth = other.getClass().getMethod("getName", null);
+ String name = (String) mth.invoke(other, null);
+ return name;
+ } catch (NoSuchMethodException e) {
+ // ignore - should never happen
+ } catch (IllegalAccessException e) {
+ // ignore - should never happen
+ } catch (InvocationTargetException e) {
+ // ignore - should never happen
+ }
+ throw new IllegalStateException("This should not happen");
+ }
+
+ /**
+ * Human readable description of this Enum item.
+ *
+ * @return String in the form type[name]
, for example:
+ * Color[Red]
. Note that the package name is stripped from
+ * the type name.
+ */
+ public String toString() {
+ if (iToString == null) {
+ String shortName = ClassUtils.getShortClassName(getEnumClass());
+ iToString = shortName + "[" + getName() + "]";
+ }
+ return iToString;
+ }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/enums/EnumUtils.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/enums/EnumUtils.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/enums/EnumUtils.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang.enums;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Utility class for accessing and manipulating {@link Enum}s.
+ *
+ * @see Enum
+ * @see ValuedEnum
+ * @author Apache Software Foundation
+ * @author Gary Gregory
+ * @since 2.1 (class existed in enum package from v1.0)
+ * @version $Id$
+ */
+public class EnumUtils {
+
+ /**
+ * Public constructor. This class should not normally be instantiated.
+ * @since 2.0
+ */
+ public EnumUtils() {
+ super();
+ }
+
+ /**
+ * Gets an Enum
object by class and name.
+ *
+ * @param enumClass the class of the Enum
to get
+ * @param name the name of the Enum to get, may be null
+ * @return the enum object
+ * @throws IllegalArgumentException if the enum class is null
+ */
+ public static Enum getEnum(Class enumClass, String name) {
+ return Enum.getEnum(enumClass, name);
+ }
+
+ /**
+ * Gets a ValuedEnum
object by class and value.
+ *
+ * @param enumClass the class of the Enum
to get
+ * @param value the value of the Enum
to get
+ * @return the enum object, or null if the enum does not exist
+ * @throws IllegalArgumentException if the enum class is null
+ */
+ public static ValuedEnum getEnum(Class enumClass, int value) {
+ return (ValuedEnum) ValuedEnum.getEnum(enumClass, value);
+ }
+
+ /**
+ * Gets the Map
of Enum
objects by
+ * name using the Enum
class.
+ *
+ * If the requested class has no enum objects an empty
+ * Map
is returned. The Map
is unmodifiable.
+ *
+ * @param enumClass the class of the Enum
to get
+ * @return the enum object Map
+ * @throws IllegalArgumentException if the enum class is null
+ * @throws IllegalArgumentException if the enum class is not a subclass
+ * of Enum
+ */
+ public static Map getEnumMap(Class enumClass) {
+ return Enum.getEnumMap(enumClass);
+ }
+
+ /**
+ * Gets the List
of Enum
objects using
+ * the Enum
class.
+ *
+ * The list is in the order that the objects were created
+ * (source code order).
+ *
+ * If the requested class has no enum objects an empty
+ * List
is returned. The List
is unmodifiable.
+ *
+ * @param enumClass the class of the Enum to get
+ * @return the enum object Map
+ * @throws IllegalArgumentException if the enum class is null
+ * @throws IllegalArgumentException if the enum class is not a subclass
+ * of Enum
+ */
+ public static List getEnumList(Class enumClass) {
+ return Enum.getEnumList(enumClass);
+ }
+
+ /**
+ * Gets an Iterator
over the Enum
objects
+ * in an Enum
class.
+ *
+ * The iterator is in the order that the objects were created
+ * (source code order).
+ *
+ * If the requested class has no enum objects an empty
+ * Iterator
is returned. The Iterator
+ * is unmodifiable.
+ *
+ * @param enumClass the class of the Enum
to get
+ * @return an Iterator
of the Enum
objects
+ * @throws IllegalArgumentException if the enum class is null
+ * @throws IllegalArgumentException if the enum class is not a subclass of Enum
+ */
+ public static Iterator iterator(Class enumClass) {
+ return Enum.getEnumList(enumClass).iterator();
+ }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/enums/ValuedEnum.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/enums/ValuedEnum.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/enums/ValuedEnum.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,236 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang.enums;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.lang.ClassUtils;
+
+/**
+ * Abstract superclass for type-safe enums with integer values suitable
+ * for use in switch
statements.
+ *
+ * NOTE:Due to the way in which Java ClassLoaders work, comparing
+ * Enum
objects should always be done using the equals() method,
+ * not ==
. The equals() method will try ==
first so
+ * in most cases the effect is the same.
+ *
+ * To use this class, it must be subclassed. For example:
+ *
+ *
+ * public final class JavaVersionEnum extends ValuedEnum {
+ * //standard enums for version of JVM
+ * public static final int JAVA1_0_VALUE = 100;
+ * public static final int JAVA1_1_VALUE = 110;
+ * public static final int JAVA1_2_VALUE = 120;
+ * public static final int JAVA1_3_VALUE = 130;
+ * public static final JavaVersionEnum JAVA1_0 = new JavaVersionEnum( "Java 1.0", JAVA1_0_VALUE );
+ * public static final JavaVersionEnum JAVA1_1 = new JavaVersionEnum( "Java 1.1", JAVA1_1_VALUE );
+ * public static final JavaVersionEnum JAVA1_2 = new JavaVersionEnum( "Java 1.2", JAVA1_2_VALUE );
+ * public static final JavaVersionEnum JAVA1_3 = new JavaVersionEnum( "Java 1.3", JAVA1_3_VALUE );
+ *
+ * private JavaVersionEnum(String name, int value) {
+ * super( name, value );
+ * }
+ *
+ * public static JavaVersionEnum getEnum(String javaVersion) {
+ * return (JavaVersionEnum) getEnum(JavaVersionEnum.class, javaVersion);
+ * }
+ *
+ * public static JavaVersionEnum getEnum(int javaVersion) {
+ * return (JavaVersionEnum) getEnum(JavaVersionEnum.class, javaVersion);
+ * }
+ *
+ * public static Map getEnumMap() {
+ * return getEnumMap(JavaVersionEnum.class);
+ * }
+ *
+ * public static List getEnumList() {
+ * return getEnumList(JavaVersionEnum.class);
+ * }
+ *
+ * public static Iterator iterator() {
+ * return iterator(JavaVersionEnum.class);
+ * }
+ * }
+ *
+ *
+ * NOTE:These are declared final
, so compilers may
+ * inline the code. Ensure you recompile everything when using final.
+ *
+ * The above class could then be used as follows:
+ *
+ *
+ * public void doSomething(JavaVersionEnum ver) {
+ * switch (ver.getValue()) {
+ * case JAVA1_0_VALUE:
+ * // ...
+ * break;
+ * case JAVA1_1_VALUE:
+ * // ...
+ * break;
+ * //...
+ * }
+ * }
+ *
+ *
+ * As shown, each enum has a name and a value. These can be accessed using
+ * getName
and getValue
.
+ *
+ * NOTE: Because the switch is ultimately sitting on top of an
+ * int, the example above is not type-safe. That is, there is nothing that
+ * checks that JAVA1_0_VALUE is a legal constant for JavaVersionEnum.
+ *
+ * The getEnum
and iterator
methods are recommended.
+ * Unfortunately, Java restrictions require these to be coded as shown in each subclass.
+ * An alternative choice is to use the {@link EnumUtils} class.
+ *
+ * @author Apache Avalon project
+ * @author Apache Software Foundation
+ * @since 2.1 (class existed in enum package from v1.0)
+ * @version $Id$
+ */
+public abstract class ValuedEnum extends Enum {
+
+ /**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = -7129650521543789085L;
+
+ /**
+ * The value contained in enum.
+ */
+ private final int iValue;
+
+ /**
+ * Constructor for enum item.
+ *
+ * @param name the name of enum item
+ * @param value the value of enum item
+ */
+ protected ValuedEnum(String name, int value) {
+ super(name);
+ iValue = value;
+ }
+
+ /**
+ * Gets an Enum
object by class and value.
+ *
+ * This method loops through the list of Enum
,
+ * thus if there are many Enum
s this will be
+ * slow.
+ *
+ * @param enumClass the class of the Enum
to get
+ * @param value the value of the Enum
to get
+ * @return the enum object, or null if the enum does not exist
+ * @throws IllegalArgumentException if the enum class is null
+ */
+ protected static Enum getEnum(Class enumClass, int value) {
+ if (enumClass == null) {
+ throw new IllegalArgumentException("The Enum Class must not be null");
+ }
+ List list = Enum.getEnumList(enumClass);
+ for (Iterator it = list.iterator(); it.hasNext();) {
+ ValuedEnum enumeration = (ValuedEnum) it.next();
+ if (enumeration.getValue() == value) {
+ return enumeration;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get value of enum item.
+ *
+ * @return the enum item's value.
+ */
+ public final int getValue() {
+ return iValue;
+ }
+
+ /**
+ * Tests for order.
+ *
+ * The default ordering is numeric by value, but this
+ * can be overridden by subclasses.
+ *
+ * NOTE: From v2.2 the enums must be of the same type.
+ * If the parameter is in a different class loader than this instance,
+ * reflection is used to compare the values.
+ *
+ * @see java.lang.Comparable#compareTo(Object)
+ * @param other the other object to compare to
+ * @return -ve if this is less than the other object, +ve if greater than,
+ * 0
of equal
+ * @throws ClassCastException if other is not an Enum
+ * @throws NullPointerException if other is null
+ */
+ public int compareTo(Object other) {
+ if (other == this) {
+ return 0;
+ }
+ if (other.getClass() != this.getClass()) {
+ if (other.getClass().getName().equals(this.getClass().getName())) {
+ return iValue - getValueInOtherClassLoader(other);
+ }
+ throw new ClassCastException(
+ "Different enum class '" + ClassUtils.getShortClassName(other.getClass()) + "'");
+ }
+ return iValue - ((ValuedEnum) other).iValue;
+ }
+
+ /**
+ * Use reflection to return an objects value.
+ *
+ * @param other the object to determine the value for
+ * @return the value
+ */
+ private int getValueInOtherClassLoader(Object other) {
+ try {
+ Method mth = other.getClass().getMethod("getValue", null);
+ Integer value = (Integer) mth.invoke(other, null);
+ return value.intValue();
+ } catch (NoSuchMethodException e) {
+ // ignore - should never happen
+ } catch (IllegalAccessException e) {
+ // ignore - should never happen
+ } catch (InvocationTargetException e) {
+ // ignore - should never happen
+ }
+ throw new IllegalStateException("This should not happen");
+ }
+
+ /**
+ * Human readable description of this Enum
item.
+ *
+ * @return String in the form type[name=value]
, for example:
+ * JavaVersion[Java 1.0=100]
. Note that the package name is
+ * stripped from the type name.
+ */
+ public String toString() {
+ if (iToString == null) {
+ String shortName = ClassUtils.getShortClassName(getEnumClass());
+ iToString = shortName + "[" + getName() + "=" + getValue() + "]";
+ }
+ return iToString;
+ }
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/enums/package.html
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/enums/package.html (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/enums/package.html (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,54 @@
+
+
+
+
+Provides an implementation of the C style enum
in the Java world.
+
+
+The classic example being an RGB color enumeration.
+
+
+public final class ColorEnum extends Enum {
+ public static final ColorEnum RED = new ColorEnum("Red");
+ public static final ColorEnum GREEN = new ColorEnum("Green");
+ public static final ColorEnum BLUE = new ColorEnum("Blue");
+
+ private ColorEnum(String color) {
+ super(color);
+ }
+
+ public static ColorEnum getEnum(String color) {
+ return (ColorEnum) getEnum(ColorEnum.class, color);
+ }
+
+ public static Map getEnumMap() {
+ return getEnumMap(ColorEnum.class);
+ }
+
+ public static List getEnumList() {
+ return getEnumList(ColorEnum.class);
+ }
+
+ public static Iterator iterator() {
+ return iterator(ColorEnum.class);
+ }
+}
+
+@since 2.1
+
+
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/CloneFailedException.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/CloneFailedException.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/CloneFailedException.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang.exception;
+
+/**
+ * Exception thrown when a clone cannot be created. In contrast to
+ * {@link CloneNotSupportedException} this is a {@link RuntimeException}.
+ *
+ * @author Apache Software Foundation
+ * @since 2.6
+ */
+public class CloneFailedException extends NestableRuntimeException {
+ // ~ Static fields/initializers ---------------------------------------------
+
+ private static final long serialVersionUID = 20091223L;
+
+ // ~ Constructors -----------------------------------------------------------
+
+ /**
+ * Constructs a CloneFailedException.
+ *
+ * @param message description of the exception
+ * @since upcoming
+ */
+ public CloneFailedException(final String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a CloneFailedException.
+ *
+ * @param cause cause of the exception
+ * @since upcoming
+ */
+ public CloneFailedException(final Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructs a CloneFailedException.
+ *
+ * @param message description of the exception
+ * @param cause cause of the exception
+ * @since upcoming
+ */
+ public CloneFailedException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/ExceptionUtils.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/ExceptionUtils.java (.../ExceptionUtils.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/ExceptionUtils.java (.../ExceptionUtils.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,55 +1,18 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang.exception;
@@ -62,21 +25,22 @@
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;
import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.ClassUtils;
+import org.apache.commons.lang.NullArgumentException;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.SystemUtils;
/**
* Provides utilities for manipulating and examining
* Throwable
objects.
*
- * @author Daniel Rall
+ * @author Apache Software Foundation
+ * @author Daniel L. Rall
* @author Dmitri Plotnikov
- * @author Stephen Colebourne
* @author Gary Gregory
* @author Pete Gieser
* @since 1.0
@@ -92,6 +56,9 @@
*/
static final String WRAPPED_MARKER = " [wrapped] ";
+ // Lock object for CAUSE_METHOD_NAMES
+ private static final Object CAUSE_METHOD_NAMES_LOCK = new Object();
+
/**
* The names of methods commonly used to access a wrapped exception.
*/
@@ -103,28 +70,47 @@
"getSourceException",
"getRootCause",
"getCausedByException",
- "getNested"
+ "getNested",
+ "getLinkedException",
+ "getNestedException",
+ "getLinkedCause",
+ "getThrowable",
};
/**
- * The Method object for JDK1.4 getCause.
+ * The Method object for Java 1.4 getCause.
*/
private static final Method THROWABLE_CAUSE_METHOD;
+
+ /**
+ * The Method object for Java 1.4 initCause.
+ */
+ private static final Method THROWABLE_INITCAUSE_METHOD;
+
static {
- Method getCauseMethod;
+ Method causeMethod;
try {
- getCauseMethod = Throwable.class.getMethod("getCause", null);
+ causeMethod = Throwable.class.getMethod("getCause", null);
} catch (Exception e) {
- getCauseMethod = null;
+ causeMethod = null;
}
- THROWABLE_CAUSE_METHOD = getCauseMethod;
+ THROWABLE_CAUSE_METHOD = causeMethod;
+ try {
+ causeMethod = Throwable.class.getMethod("initCause", new Class[]{Throwable.class});
+ } catch (Exception e) {
+ causeMethod = null;
+ }
+ THROWABLE_INITCAUSE_METHOD = causeMethod;
}
/**
- * Public constructor allows an instance of ExceptionUtils
- * to be created, although that is not normally necessary.
+ *
+ * Public constructor allows an instance of ExceptionUtils
to be created, although that is not
+ * normally necessary.
+ *
*/
public ExceptionUtils() {
+ super();
}
//-----------------------------------------------------------------------
@@ -137,16 +123,132 @@
* @since 2.0
*/
public static void addCauseMethodName(String methodName) {
+ if (StringUtils.isNotEmpty(methodName) && !isCauseMethodName(methodName)) {
+ List list = getCauseMethodNameList();
+ if (list.add(methodName)) {
+ synchronized(CAUSE_METHOD_NAMES_LOCK) {
+ CAUSE_METHOD_NAMES = toArray(list);
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes from the list of method names used in the search for Throwable
+ * objects.
+ *
+ * @param methodName the methodName to remove from the list, null
+ * and empty strings are ignored
+ * @since 2.1
+ */
+ public static void removeCauseMethodName(String methodName) {
if (StringUtils.isNotEmpty(methodName)) {
- List list = new ArrayList(Arrays.asList(CAUSE_METHOD_NAMES));
- list.add(methodName);
- CAUSE_METHOD_NAMES = (String[]) list.toArray(new String[list.size()]);
+ List list = getCauseMethodNameList();
+ if (list.remove(methodName)) {
+ synchronized(CAUSE_METHOD_NAMES_LOCK) {
+ CAUSE_METHOD_NAMES = toArray(list);
+ }
+ }
}
}
/**
- * Introspects the Throwable
to obtain the cause.
+ * Sets the cause of a Throwable
using introspection, allowing
+ * source code compatibility between pre-1.4 and post-1.4 Java releases.
+ *
+ * The typical use of this method is inside a constructor as in
+ * the following example:
+ *
+ *
+ * import org.apache.commons.lang.exception.ExceptionUtils;
+ *
+ * public class MyException extends Exception {
+ *
+ * public MyException(String msg) {
+ * super(msg);
+ * }
+ *
+ * public MyException(String msg, Throwable cause) {
+ * super(msg);
+ * ExceptionUtils.setCause(this, cause);
+ * }
+ * }
+ *
+ *
+ * @param target the target Throwable
+ * @param cause the Throwable
to set in the target
+ * @return a true
if the target has been modified
+ * @since 2.2
+ */
+ public static boolean setCause(Throwable target, Throwable cause) {
+ if (target == null) {
+ throw new NullArgumentException("target");
+ }
+ Object[] causeArgs = new Object[]{cause};
+ boolean modifiedTarget = false;
+ if (THROWABLE_INITCAUSE_METHOD != null) {
+ try {
+ THROWABLE_INITCAUSE_METHOD.invoke(target, causeArgs);
+ modifiedTarget = true;
+ } catch (IllegalAccessException ignored) {
+ // Exception ignored.
+ } catch (InvocationTargetException ignored) {
+ // Exception ignored.
+ }
+ }
+ try {
+ Method setCauseMethod = target.getClass().getMethod("setCause", new Class[]{Throwable.class});
+ setCauseMethod.invoke(target, causeArgs);
+ modifiedTarget = true;
+ } catch (NoSuchMethodException ignored) {
+ // Exception ignored.
+ } catch (IllegalAccessException ignored) {
+ // Exception ignored.
+ } catch (InvocationTargetException ignored) {
+ // Exception ignored.
+ }
+ return modifiedTarget;
+ }
+
+ /**
+ * Returns the given list as a String[]
.
+ * @param list a list to transform.
+ * @return the given list as a String[]
.
+ */
+ private static String[] toArray(List list) {
+ return (String[]) list.toArray(new String[list.size()]);
+ }
+
+ /**
+ * Returns {@link #CAUSE_METHOD_NAMES} as a List.
+ *
+ * @return {@link #CAUSE_METHOD_NAMES} as a List.
+ */
+ private static ArrayList getCauseMethodNameList() {
+ synchronized(CAUSE_METHOD_NAMES_LOCK) {
+ return new ArrayList(Arrays.asList(CAUSE_METHOD_NAMES));
+ }
+ }
+
+ /**
+ * Tests if the list of method names used in the search for Throwable
+ * objects include the given name.
*
+ * @param methodName the methodName to search in the list.
+ * @return if the list of method names used in the search for Throwable
+ * objects include the given name.
+ * @since 2.1
+ */
+ public static boolean isCauseMethodName(String methodName) {
+ synchronized(CAUSE_METHOD_NAMES_LOCK) {
+ return ArrayUtils.indexOf(CAUSE_METHOD_NAMES, methodName) >= 0;
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Introspects the Throwable
to obtain the cause.
+ *
* The method searches for methods with specific names that return a
* Throwable
object. This will pick up most wrapping exceptions,
* including those from JDK 1.4, and
@@ -167,33 +269,37 @@
*
*
In the absence of any such method, the object is inspected for a
* detail
field assignable to a Throwable
.
- *
+ *
* If none of the above is found, returns null
.
*
* @param throwable the throwable to introspect for a cause, may be null
* @return the cause of the Throwable
,
* null
if none found or null throwable input
+ * @since 1.0
*/
public static Throwable getCause(Throwable throwable) {
- return getCause(throwable, CAUSE_METHOD_NAMES);
+ synchronized(CAUSE_METHOD_NAMES_LOCK) {
+ return getCause(throwable, CAUSE_METHOD_NAMES);
+ }
}
/**
* Introspects the Throwable
to obtain the cause.
- *
+ *
*
* - Try known exception types.
* - Try the supplied array of method names.
* - Try the field 'detail'.
*
- *
+ *
* A null
set of method names means use the default set.
* A null
in the set of method names will be ignored.
*
* @param throwable the throwable to introspect for a cause, may be null
* @param methodNames the method names, null treated as default set
* @return the cause of the Throwable
,
* null
if none found or null throwable input
+ * @since 1.0
*/
public static Throwable getCause(Throwable throwable, String[] methodNames) {
if (throwable == null) {
@@ -202,7 +308,9 @@
Throwable cause = getCauseUsingWellKnownTypes(throwable);
if (cause == null) {
if (methodNames == null) {
- methodNames = CAUSE_METHOD_NAMES;
+ synchronized(CAUSE_METHOD_NAMES_LOCK) {
+ methodNames = CAUSE_METHOD_NAMES;
+ }
}
for (int i = 0; i < methodNames.length; i++) {
String methodName = methodNames[i];
@@ -223,24 +331,24 @@
/**
* Introspects the Throwable
to obtain the root cause.
- *
+ *
* This method walks through the exception chain to the last element,
* "root" of the tree, using {@link #getCause(Throwable)}, and
* returns that exception.
*
+ * From version 2.2, this method handles recursive cause structures
+ * that might otherwise cause infinite loops. If the throwable parameter
+ * has a cause of itself, then null will be returned. If the throwable
+ * parameter cause chain loops, the last element in the chain before the
+ * loop is returned.
+ *
* @param throwable the throwable to get the root cause for, may be null
* @return the root cause of the Throwable
,
* null
if none found or null throwable input
*/
public static Throwable getRootCause(Throwable throwable) {
- Throwable cause = getCause(throwable);
- if (cause != null) {
- throwable = cause;
- while ((throwable = getCause(throwable)) != null) {
- cause = throwable;
- }
- }
- return cause;
+ List list = getThrowableList(throwable);
+ return (list.size() < 2 ? null : (Throwable)list.get(list.size() - 1));
}
/**
@@ -267,7 +375,7 @@
/**
* Finds a Throwable
by method name.
- *
+ *
* @param throwable the exception to examine
* @param methodName the name of the method to find and invoke
* @return the wrapped exception, or null
if not found
@@ -277,23 +385,28 @@
try {
method = throwable.getClass().getMethod(methodName, null);
} catch (NoSuchMethodException ignored) {
+ // exception ignored
} catch (SecurityException ignored) {
+ // exception ignored
}
if (method != null && Throwable.class.isAssignableFrom(method.getReturnType())) {
try {
return (Throwable) method.invoke(throwable, ArrayUtils.EMPTY_OBJECT_ARRAY);
} catch (IllegalAccessException ignored) {
+ // exception ignored
} catch (IllegalArgumentException ignored) {
+ // exception ignored
} catch (InvocationTargetException ignored) {
+ // exception ignored
}
}
return null;
}
/**
* Finds a Throwable
by field name.
- *
+ *
* @param throwable the exception to examine
* @param fieldName the name of the attribute to examine
* @return the wrapped exception, or null
if not found
@@ -303,14 +416,18 @@
try {
field = throwable.getClass().getField(fieldName);
} catch (NoSuchFieldException ignored) {
+ // exception ignored
} catch (SecurityException ignored) {
+ // exception ignored
}
if (field != null && Throwable.class.isAssignableFrom(field.getType())) {
try {
return (Throwable) field.get(throwable);
} catch (IllegalAccessException ignored) {
+ // exception ignored
} catch (IllegalArgumentException ignored) {
+ // exception ignored
}
}
return null;
@@ -319,19 +436,19 @@
//-----------------------------------------------------------------------
/**
* Checks if the Throwable class has a getCause
method.
- *
+ *
* This is true for JDK 1.4 and above.
- *
+ *
* @return true if Throwable is nestable
* @since 2.0
*/
public static boolean isThrowableNested() {
- return (THROWABLE_CAUSE_METHOD != null);
+ return THROWABLE_CAUSE_METHOD != null;
}
/**
* Checks whether this Throwable
class can store a cause.
- *
+ *
* This method does not check whether it actually does store a cause.
*
* @param throwable the Throwable
to examine, may be null
@@ -354,14 +471,18 @@
}
Class cls = throwable.getClass();
- for (int i = 0, isize = CAUSE_METHOD_NAMES.length; i < isize; i++) {
- try {
- Method method = cls.getMethod(CAUSE_METHOD_NAMES[i], null);
- if (method != null && Throwable.class.isAssignableFrom(method.getReturnType())) {
- return true;
+ synchronized(CAUSE_METHOD_NAMES_LOCK) {
+ for (int i = 0, isize = CAUSE_METHOD_NAMES.length; i < isize; i++) {
+ try {
+ Method method = cls.getMethod(CAUSE_METHOD_NAMES[i], null);
+ if (method != null && Throwable.class.isAssignableFrom(method.getReturnType())) {
+ return true;
+ }
+ } catch (NoSuchMethodException ignored) {
+ // exception ignored
+ } catch (SecurityException ignored) {
+ // exception ignored
}
- } catch (NoSuchMethodException ignored) {
- } catch (SecurityException ignored) {
}
}
@@ -371,7 +492,9 @@
return true;
}
} catch (NoSuchFieldException ignored) {
+ // exception ignored
} catch (SecurityException ignored) {
+ // exception ignored
}
return false;
@@ -381,81 +504,174 @@
/**
*
Counts the number of Throwable
objects in the
* exception chain.
- *
+ *
* A throwable without cause will return 1
.
* A throwable with one cause will return 2
and so on.
* A null
throwable will return 0
.
- *
+ *
+ * From version 2.2, this method handles recursive cause structures
+ * that might otherwise cause infinite loops. The cause chain is
+ * processed until the end is reached, or until the next item in the
+ * chain is already in the result set.
+ *
* @param throwable the throwable to inspect, may be null
* @return the count of throwables, zero if null input
*/
public static int getThrowableCount(Throwable throwable) {
- int count = 0;
- while (throwable != null) {
- count++;
- throwable = ExceptionUtils.getCause(throwable);
- }
- return count;
+ return getThrowableList(throwable).size();
}
/**
* Returns the list of Throwable
objects in the
* exception chain.
- *
+ *
* A throwable without cause will return an array containing
* one element - the input throwable.
* A throwable with one cause will return an array containing
* two elements. - the input throwable and the cause throwable.
- * A null
throwable will return an array size zero.
+ * A null
throwable will return an array of size zero.
*
+ * From version 2.2, this method handles recursive cause structures
+ * that might otherwise cause infinite loops. The cause chain is
+ * processed until the end is reached, or until the next item in the
+ * chain is already in the result set.
+ *
+ * @see #getThrowableList(Throwable)
* @param throwable the throwable to inspect, may be null
* @return the array of throwables, never null
*/
public static Throwable[] getThrowables(Throwable throwable) {
+ List list = getThrowableList(throwable);
+ return (Throwable[]) list.toArray(new Throwable[list.size()]);
+ }
+
+ /**
+ * Returns the list of Throwable
objects in the
+ * exception chain.
+ *
+ * A throwable without cause will return a list containing
+ * one element - the input throwable.
+ * A throwable with one cause will return a list containing
+ * two elements. - the input throwable and the cause throwable.
+ * A null
throwable will return a list of size zero.
+ *
+ * This method handles recursive cause structures that might
+ * otherwise cause infinite loops. The cause chain is processed until
+ * the end is reached, or until the next item in the chain is already
+ * in the result set.
+ *
+ * @param throwable the throwable to inspect, may be null
+ * @return the list of throwables, never null
+ * @since Commons Lang 2.2
+ */
+ public static List getThrowableList(Throwable throwable) {
List list = new ArrayList();
- while (throwable != null) {
+ while (throwable != null && list.contains(throwable) == false) {
list.add(throwable);
throwable = ExceptionUtils.getCause(throwable);
}
- return (Throwable[]) list.toArray(new Throwable[list.size()]);
+ return list;
}
//-----------------------------------------------------------------------
/**
* Returns the (zero based) index of the first Throwable
- * that matches the specified type in the exception chain.
- *
+ * that matches the specified class (exactly) in the exception chain.
+ * Subclasses of the specified class do not match - see
+ * {@link #indexOfType(Throwable, Class)} for the opposite.
+ *
* A null
throwable returns -1
.
* A null
type returns -1
.
* No match in the chain returns -1
.
*
* @param throwable the throwable to inspect, may be null
- * @param type the type to search for
+ * @param clazz the class to search for, subclasses do not match, null returns -1
* @return the index into the throwable chain, -1 if no match or null input
*/
- public static int indexOfThrowable(Throwable throwable, Class type) {
- return indexOfThrowable(throwable, type, 0);
+ public static int indexOfThrowable(Throwable throwable, Class clazz) {
+ return indexOf(throwable, clazz, 0, false);
}
/**
* Returns the (zero based) index of the first Throwable
* that matches the specified type in the exception chain from
- * a specified index.
- *
+ * a specified index.
+ * Subclasses of the specified class do not match - see
+ * {@link #indexOfType(Throwable, Class, int)} for the opposite.
+ *
* A null
throwable returns -1
.
* A null
type returns -1
.
* No match in the chain returns -1
.
* A negative start index is treated as zero.
* A start index greater than the number of throwables returns -1
.
*
* @param throwable the throwable to inspect, may be null
- * @param type the type to search for
+ * @param clazz the class to search for, subclasses do not match, null returns -1
* @param fromIndex the (zero based) index of the starting position,
* negative treated as zero, larger than chain size returns -1
* @return the index into the throwable chain, -1 if no match or null input
*/
- public static int indexOfThrowable(Throwable throwable, Class type, int fromIndex) {
- if (throwable == null) {
+ public static int indexOfThrowable(Throwable throwable, Class clazz, int fromIndex) {
+ return indexOf(throwable, clazz, fromIndex, false);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Returns the (zero based) index of the first Throwable
+ * that matches the specified class or subclass in the exception chain.
+ * Subclasses of the specified class do match - see
+ * {@link #indexOfThrowable(Throwable, Class)} for the opposite.
+ *
+ * A null
throwable returns -1
.
+ * A null
type returns -1
.
+ * No match in the chain returns -1
.
+ *
+ * @param throwable the throwable to inspect, may be null
+ * @param type the type to search for, subclasses match, null returns -1
+ * @return the index into the throwable chain, -1 if no match or null input
+ * @since 2.1
+ */
+ public static int indexOfType(Throwable throwable, Class type) {
+ return indexOf(throwable, type, 0, true);
+ }
+
+ /**
+ * Returns the (zero based) index of the first Throwable
+ * that matches the specified type in the exception chain from
+ * a specified index.
+ * Subclasses of the specified class do match - see
+ * {@link #indexOfThrowable(Throwable, Class)} for the opposite.
+ *
+ * A null
throwable returns -1
.
+ * A null
type returns -1
.
+ * No match in the chain returns -1
.
+ * A negative start index is treated as zero.
+ * A start index greater than the number of throwables returns -1
.
+ *
+ * @param throwable the throwable to inspect, may be null
+ * @param type the type to search for, subclasses match, null returns -1
+ * @param fromIndex the (zero based) index of the starting position,
+ * negative treated as zero, larger than chain size returns -1
+ * @return the index into the throwable chain, -1 if no match or null input
+ * @since 2.1
+ */
+ public static int indexOfType(Throwable throwable, Class type, int fromIndex) {
+ return indexOf(throwable, type, fromIndex, true);
+ }
+
+ /**
+ * Worker method for the indexOfType
methods.
+ *
+ * @param throwable the throwable to inspect, may be null
+ * @param type the type to search for, subclasses match, null returns -1
+ * @param fromIndex the (zero based) index of the starting position,
+ * negative treated as zero, larger than chain size returns -1
+ * @param subclass if true
, compares with {@link Class#isAssignableFrom(Class)}, otherwise compares
+ * using references
+ * @return index of the type
within throwables nested withing the specified throwable
+ */
+ private static int indexOf(Throwable throwable, Class type, int fromIndex, boolean subclass) {
+ if (throwable == null || type == null) {
return -1;
}
if (fromIndex < 0) {
@@ -465,10 +681,18 @@
if (fromIndex >= throwables.length) {
return -1;
}
- for (int i = fromIndex; i < throwables.length; i++) {
- if (throwables[i].getClass().equals(type)) {
- return i;
+ if (subclass) {
+ for (int i = fromIndex; i < throwables.length; i++) {
+ if (type.isAssignableFrom(throwables[i].getClass())) {
+ return i;
+ }
}
+ } else {
+ for (int i = fromIndex; i < throwables.length; i++) {
+ if (type.equals(throwables[i].getClass())) {
+ return i;
+ }
+ }
}
return -1;
}
@@ -477,15 +701,18 @@
/**
* Prints a compact stack trace for the root cause of a throwable
* to System.err
.
- *
+ *
* The compact stack trace starts with the root cause and prints
* stack frames up to the place where it was caught and wrapped.
* Then it prints the wrapped exception and continues with stack frames
* until the wrapper exception is caught and wrapped again, etc.
*
+ * The output of this method is consistent across JDK versions.
+ * Note that this is the opposite order to the JDK1.4 display.
+ *
* The method is equivalent to printStackTrace
for throwables
* that don't have nested causes.
- *
+ *
* @param throwable the throwable to output
* @since 2.0
*/
@@ -501,9 +728,12 @@
* Then it prints the wrapped exception and continues with stack frames
* until the wrapper exception is caught and wrapped again, etc.
*
+ * The output of this method is consistent across JDK versions.
+ * Note that this is the opposite order to the JDK1.4 display.
+ *
* The method is equivalent to printStackTrace
for throwables
* that don't have nested causes.
- *
+ *
* @param throwable the throwable to output, may be null
* @param stream the stream to output to, may not be null
* @throws IllegalArgumentException if the stream is null
@@ -531,9 +761,12 @@
* Then it prints the wrapped exception and continues with stack frames
* until the wrapper exception is caught and wrapped again, etc.
*
+ * The output of this method is consistent across JDK versions.
+ * Note that this is the opposite order to the JDK1.4 display.
+ *
* The method is equivalent to printStackTrace
for throwables
* that don't have nested causes.
- *
+ *
* @param throwable the throwable to output, may be null
* @param writer the writer to output to, may not be null
* @throws IllegalArgumentException if the writer is null
@@ -557,7 +790,12 @@
/**
* Creates a compact stack trace for the root cause of the supplied
* Throwable
.
- *
+ *
+ * The output of this method is consistent across JDK versions.
+ * It consists of the root exception followed by each of its wrapping
+ * exceptions separated by '[wrapped]'. Note that this is the opposite
+ * order to the JDK1.4 display.
+ *
* @param throwable the throwable to examine, may be null
* @return an array of stack trace frames, never null
* @since 2.0
@@ -590,7 +828,7 @@
/**
* Removes common frames from the cause trace given the two stack traces.
- *
+ *
* @param causeFrames stack trace of a cause throwable
* @param wrapperFrames stack trace of a wrapper throwable
* @throws IllegalArgumentException if either argument is null
@@ -617,22 +855,11 @@
//-----------------------------------------------------------------------
/**
- * Gets the stack trace from a Throwable as a String.
- *
- * @param throwable the Throwable
to be examined
- * @return the stack trace as generated by the exception's
- * printStackTrace(PrintWriter)
method
- */
- public static String getStackTrace(Throwable throwable) {
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw, true);
- throwable.printStackTrace(pw);
- return sw.getBuffer().toString();
- }
-
- /**
* A way to get the entire nested stack-trace of an throwable.
*
+ * The result of this method is highly dependent on the JDK version
+ * and whether the exceptions override printStackTrace or not.
+ *
* @param throwable the Throwable
to be examined
* @return the nested stack trace, with the root cause first
* @since 2.0
@@ -652,11 +879,35 @@
//-----------------------------------------------------------------------
/**
+ * Gets the stack trace from a Throwable as a String.
+ *
+ * The result of this method vary by JDK version as this method
+ * uses {@link Throwable#printStackTrace(java.io.PrintWriter)}.
+ * On JDK1.3 and earlier, the cause exception will not be shown
+ * unless the specified throwable alters printStackTrace.
+ *
+ * @param throwable the Throwable
to be examined
+ * @return the stack trace as generated by the exception's
+ * printStackTrace(PrintWriter)
method
+ */
+ public static String getStackTrace(Throwable throwable) {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw, true);
+ throwable.printStackTrace(pw);
+ return sw.getBuffer().toString();
+ }
+
+ /**
* Captures the stack trace associated with the specified
* Throwable
object, decomposing it into a list of
* stack frames.
*
- * @param throwable the Throwable
to exaamine, may be null
+ * The result of this method vary by JDK version as this method
+ * uses {@link Throwable#printStackTrace(java.io.PrintWriter)}.
+ * On JDK1.3 and earlier, the cause exception will not be shown
+ * unless the specified throwable alters printStackTrace.
+ *
+ * @param throwable the Throwable
to examine, may be null
* @return an array of strings describing each stack frame, never null
*/
public static String[] getStackFrames(Throwable throwable) {
@@ -666,25 +917,33 @@
return getStackFrames(getStackTrace(throwable));
}
+ //-----------------------------------------------------------------------
/**
+ * Returns an array where each element is a line from the argument.
+ *
+ * The end of line is determined by the value of {@link SystemUtils#LINE_SEPARATOR}.
+ *
* Functionality shared between the
* getStackFrames(Throwable)
methods of this and the
- * {@link org.apache.commons.lang.exception.NestableDelegate}
- * classes.
+ * {@link org.apache.commons.lang.exception.NestableDelegate} classes.
+ *
+ * @param stackTrace a stack trace String
+ * @return an array where each element is a line from the argument
*/
static String[] getStackFrames(String stackTrace) {
String linebreak = SystemUtils.LINE_SEPARATOR;
StringTokenizer frames = new StringTokenizer(stackTrace, linebreak);
- List list = new LinkedList();
+ List list = new ArrayList();
while (frames.hasMoreTokens()) {
list.add(frames.nextToken());
}
- return (String[]) list.toArray(new String[list.size()]);
+ return toArray(list);
}
/**
* Produces a List
of stack frames - the message
- * is not included.
+ * is not included. Only the trace of the specified exception is
+ * returned, any caused by trace is stripped.
*
* This works in most cases - it will only fail if the exception
* message contains a line that starts with:
@@ -697,7 +956,7 @@
String stackTrace = getStackTrace(t);
String linebreak = SystemUtils.LINE_SEPARATOR;
StringTokenizer frames = new StringTokenizer(stackTrace, linebreak);
- List list = new LinkedList();
+ List list = new ArrayList();
boolean traceStarted = false;
while (frames.hasMoreTokens()) {
String token = frames.nextToken();
@@ -712,5 +971,42 @@
}
return list;
}
-
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets a short message summarising the exception.
+ *
+ * The message returned is of the form
+ * {ClassNameWithoutPackage}: {ThrowableMessage}
+ *
+ * @param th the throwable to get a message for, null returns empty string
+ * @return the message, non-null
+ * @since Commons Lang 2.2
+ */
+ public static String getMessage(Throwable th) {
+ if (th == null) {
+ return "";
+ }
+ String clsName = ClassUtils.getShortClassName(th, null);
+ String msg = th.getMessage();
+ return clsName + ": " + StringUtils.defaultString(msg);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets a short message summarising the root cause exception.
+ *
+ * The message returned is of the form
+ * {ClassNameWithoutPackage}: {ThrowableMessage}
+ *
+ * @param th the throwable to get a message for, null returns empty string
+ * @return the message, non-null
+ * @since Commons Lang 2.2
+ */
+ public static String getRootCauseMessage(Throwable th) {
+ Throwable root = ExceptionUtils.getRootCause(th);
+ root = (root == null ? th : root);
+ return getMessage(root);
+ }
+
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/Nestable.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/Nestable.java (.../Nestable.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/Nestable.java (.../Nestable.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,55 +1,18 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang.exception;
@@ -61,7 +24,7 @@
* extensions which would like to be able to nest root exceptions
* inside themselves.
*
- * @author Daniel Rall
+ * @author Daniel L. Rall
* @author Kasper Nielsen
* @author Steven Caswell
* @author Pete Gieser
@@ -88,7 +51,7 @@
/**
* Returns the error message of the Throwable
in the chain
- * of Throwable
s at the specified index, numbererd from 0.
+ * of Throwable
s at the specified index, numbered from 0.
*
* @param index the index of the Throwable
in the chain of
* Throwable
s
@@ -114,7 +77,7 @@
/**
* Returns the Throwable
in the chain of
- * Throwable
s at the specified index, numbererd from 0.
+ * Throwable
s at the specified index, numbered from 0.
*
* @param index the index, numbered from 0, of the Throwable
in
* the chain of Throwable
s
@@ -144,22 +107,34 @@
/**
* Returns the index, numbered from 0, of the first occurrence of the
- * specified type in the chain of Throwable
s, or -1 if the
- * specified type is not found in the chain.
+ * specified type, or a subclass, in the chain of Throwable
s.
+ * The method returns -1 if the specified type is not found in the chain.
+ *
+ * NOTE: From v2.1, we have clarified the Nestable
interface
+ * such that this method matches subclasses.
+ * If you want to NOT match subclasses, please use
+ * {@link ExceptionUtils#indexOfThrowable(Throwable, Class)}
+ * (which is avaiable in all versions of lang).
*
- * @param type Class
to be found
+ * @param type the type to find, subclasses match, null returns -1
* @return index of the first occurrence of the type in the chain, or -1 if
* the type is not found
*/
public int indexOfThrowable(Class type);
/**
* Returns the index, numbered from 0, of the first Throwable
- * that matches the specified type in the chain of Throwable
s
- * with an index greater than or equal to the specified index, or -1 if
- * the type is not found.
+ * that matches the specified type, or a subclass, in the chain of Throwable
s
+ * with an index greater than or equal to the specified index.
+ * The method returns -1 if the specified type is not found in the chain.
+ *
+ * NOTE: From v2.1, we have clarified the Nestable
interface
+ * such that this method matches subclasses.
+ * If you want to NOT match subclasses, please use
+ * {@link ExceptionUtils#indexOfThrowable(Throwable, Class, int)}
+ * (which is avaiable in all versions of lang).
*
- * @param type Class
to be found
+ * @param type the type to find, subclasses match, null returns -1
* @param fromIndex the index, numbered from 0, of the starting position in
* the chain to be searched
* @return index of the first occurrence of the type in the chain, or -1 if
@@ -181,7 +156,7 @@
/**
* Prints the stack trace of this exception to the specified print
- * stream. Includes inforamation from the exception, if any,
+ * stream. Includes information from the exception, if any,
* which caused this exception.
*
* @param out PrintStream
to use for output.
@@ -190,8 +165,8 @@
/**
* Prints the stack trace for this exception only--root cause not
- * included--using the provided writer. Used by {@link
- * org.apache.commons.lang.exception.NestableDelegate} to write
+ * included--using the provided writer. Used by
+ * {@link org.apache.commons.lang.exception.NestableDelegate} to write
* individual stack traces to a buffer. The implementation of
* this method should call
* super.printStackTrace(out);
in most cases.
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/NestableDelegate.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/NestableDelegate.java (.../NestableDelegate.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/NestableDelegate.java (.../NestableDelegate.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,55 +1,18 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang.exception;
@@ -72,18 +35,25 @@
* {@link org.apache.commons.lang.exception.NestableRuntimeException NestableRuntimeException}.
*
*
+ * @author Apache Software Foundation
* @author Rafal Krzewski
- * @author Daniel Rall
+ * @author Daniel L. Rall
* @author Kasper Nielsen
* @author Steven Caswell
* @author Sean C. Sullivan
- * @author Stephen Colebourne
* @since 1.0
* @version $Id$
*/
public class NestableDelegate implements Serializable {
/**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
* Constructor error message.
*/
private transient static final String MUST_BE_THROWABLE =
@@ -100,16 +70,32 @@
/**
* Whether to print the stack trace top-down.
* This public flag may be set by calling code, typically in initialisation.
+ * This exists for backwards compatability, setting it to false will return
+ * the library to v1.0 behaviour (but will affect all users of the library
+ * in the classloader).
* @since 2.0
*/
public static boolean topDown = true;
/**
* Whether to trim the repeated stack trace.
* This public flag may be set by calling code, typically in initialisation.
+ * This exists for backwards compatability, setting it to false will return
+ * the library to v1.0 behaviour (but will affect all users of the library
+ * in the classloader).
* @since 2.0
*/
public static boolean trimStackFrames = true;
+
+ /**
+ * Whether to match subclasses via indexOf.
+ * This public flag may be set by calling code, typically in initialisation.
+ * This exists for backwards compatability, setting it to false will return
+ * the library to v2.0 behaviour (but will affect all users of the library
+ * in the classloader).
+ * @since 2.1
+ */
+ public static boolean matchSubclasses = true;
/**
* Constructs a new NestableDelegate
instance to manage the
@@ -128,68 +114,54 @@
}
/**
- * Returns the error message of the Throwable
in the chain
- * of Throwable
s at the specified index, numbererd from 0.
- *
- * @param index the index of the Throwable
in the chain of
- * Throwable
s
- * @return the error message, or null if the Throwable
at the
- * specified index in the chain does not contain a message
- * @throws IndexOutOfBoundsException if the index
argument is
- * negative or not less than the count of Throwable
s in the
- * chain
+ * Returns the error message of the Throwable
in the chain of Throwable
s at the
+ * specified index, numbered from 0.
+ *
+ * @param index
+ * the index of the Throwable
in the chain of Throwable
s
+ * @return the error message, or null if the Throwable
at the specified index in the chain does not
+ * contain a message
+ * @throws IndexOutOfBoundsException
+ * if the index
argument is negative or not less than the count of Throwable
s
+ * in the chain
* @since 2.0
*/
public String getMessage(int index) {
Throwable t = this.getThrowable(index);
if (Nestable.class.isInstance(t)) {
return ((Nestable) t).getMessage(0);
- } else {
- return t.getMessage();
}
+ return t.getMessage();
}
/**
- * Returns the full message contained by the Nestable
- * and any nested Throwable
s.
- *
- * @param baseMsg the base message to use when creating the full
- * message. Should be generally be called via
- * nestableHelper.getMessage(super.getMessage())
,
- * where super
is an instance of {@link
- * java.lang.Throwable}.
- * @return The concatenated message for this and all nested
- * Throwable
s
+ * Returns the full message contained by the Nestable
and any nested Throwable
s.
+ *
+ * @param baseMsg
+ * the base message to use when creating the full message. Should be generally be called via
+ * nestableHelper.getMessage(super.getMessage())
, where super
is an
+ * instance of {@link java.lang.Throwable}.
+ * @return The concatenated message for this and all nested Throwable
s
* @since 2.0
*/
public String getMessage(String baseMsg) {
- StringBuffer msg = new StringBuffer();
- if (baseMsg != null) {
- msg.append(baseMsg);
- }
-
Throwable nestedCause = ExceptionUtils.getCause(this.nestable);
- if (nestedCause != null) {
- String causeMsg = nestedCause.getMessage();
- if (causeMsg != null) {
- if (baseMsg != null) {
- msg.append(": ");
- }
- msg.append(causeMsg);
- }
-
+ String causeMsg = nestedCause == null ? null : nestedCause.getMessage();
+ if (nestedCause == null || causeMsg == null) {
+ return baseMsg; // may be null, which is a valid result
}
- return (msg.length() > 0 ? msg.toString() : null);
+ if (baseMsg == null) {
+ return causeMsg;
+ }
+ return baseMsg + ": " + causeMsg;
}
/**
- * Returns the error message of this and any nested Throwable
s
- * in an array of Strings, one element for each message. Any
- * Throwable
not containing a message is represented in the
- * array by a null. This has the effect of cause the length of the returned
- * array to be equal to the result of the {@link #getThrowableCount()}
- * operation.
- *
+ * Returns the error message of this and any nested Throwable
s in an array of Strings, one element
+ * for each message. Any Throwable
not containing a message is represented in the array by a null.
+ * This has the effect of cause the length of the returned array to be equal to the result of the
+ * {@link #getThrowableCount()} operation.
+ *
* @return the error messages
* @since 2.0
*/
@@ -207,7 +179,7 @@
/**
* Returns the Throwable
in the chain of
- * Throwable
s at the specified index, numbererd from 0.
+ * Throwable
s at the specified index, numbered from 0.
*
* @param index the index, numbered from 0, of the Throwable
in
* the chain of Throwable
s
@@ -250,11 +222,19 @@
/**
* Returns the index, numbered from 0, of the first Throwable
- * that matches the specified type in the chain of Throwable
s
- * held in this delegate's Nestable
with an index greater than
- * or equal to the specified index, or -1 if the type is not found.
+ * that matches the specified type, or a subclass, in the chain of Throwable
s
+ * with an index greater than or equal to the specified index.
+ * The method returns -1 if the specified type is not found in the chain.
+ *
+ * NOTE: From v2.1, we have clarified the Nestable
interface
+ * such that this method matches subclasses.
+ * If you want to NOT match subclasses, please use
+ * {@link ExceptionUtils#indexOfThrowable(Throwable, Class, int)}
+ * (which is avaiable in all versions of lang).
+ * An alternative is to use the public static flag {@link #matchSubclasses}
+ * on NestableDelegate
, however this is not recommended.
*
- * @param type Class
to be found
+ * @param type the type to find, subclasses match, null returns -1
* @param fromIndex the index, numbered from 0, of the starting position in
* the chain to be searched
* @return index of the first occurrence of the type in the chain, or -1 if
@@ -265,6 +245,9 @@
* @since 2.0
*/
public int indexOfThrowable(Class type, int fromIndex) {
+ if (type == null) {
+ return -1;
+ }
if (fromIndex < 0) {
throw new IndexOutOfBoundsException("The start index was out of bounds: " + fromIndex);
}
@@ -273,10 +256,18 @@
throw new IndexOutOfBoundsException("The start index was out of bounds: "
+ fromIndex + " >= " + throwables.length);
}
- for (int i = fromIndex; i < throwables.length; i++) {
- if (throwables[i].getClass().equals(type)) {
- return i;
+ if (matchSubclasses) {
+ for (int i = fromIndex; i < throwables.length; i++) {
+ if (type.isAssignableFrom(throwables[i].getClass())) {
+ return i;
+ }
}
+ } else {
+ for (int i = fromIndex; i < throwables.length; i++) {
+ if (type.equals(throwables[i].getClass())) {
+ return i;
+ }
+ }
}
return -1;
}
@@ -344,16 +335,19 @@
}
// Remove the repeated lines in the stack
- if (trimStackFrames) trimStackFrames(stacks);
+ if (trimStackFrames) {
+ trimStackFrames(stacks);
+ }
synchronized (out) {
for (Iterator iter=stacks.iterator(); iter.hasNext();) {
String[] st = (String[]) iter.next();
for (int i=0, len=st.length; i < len; i++) {
out.println(st[i]);
}
- if (iter.hasNext())
+ if (iter.hasNext()) {
out.print(separatorLine);
+ }
}
}
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/NestableError.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/NestableError.java (.../NestableError.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/NestableError.java (.../NestableError.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,55 +1,18 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang.exception;
@@ -59,14 +22,21 @@
/**
* The base class of all errors which can contain other exceptions.
*
- * @author Daniel Rall
+ * @author Daniel L. Rall
* @see org.apache.commons.lang.exception.NestableException
* @since 1.0
* @version $Id$
*/
public class NestableError extends Error implements Nestable {
/**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
* The helper instance which contains much of the code which we
* delegate to.
*/
@@ -121,6 +91,9 @@
this.cause = cause;
}
+ /**
+ * {@inheritDoc}
+ */
public Throwable getCause() {
return cause;
}
@@ -129,6 +102,8 @@
* Returns the detail message string of this throwable. If it was
* created with a null message, returns the following:
* (cause==null ? null : cause.toString()).
+ *
+ * @return String message string of the throwable
*/
public String getMessage() {
if (super.getMessage() != null) {
@@ -140,50 +115,82 @@
}
}
+ /**
+ * {@inheritDoc}
+ */
public String getMessage(int index) {
if (index == 0) {
return super.getMessage();
- } else {
- return delegate.getMessage(index);
}
+ return delegate.getMessage(index);
}
+ /**
+ * {@inheritDoc}
+ */
public String[] getMessages() {
return delegate.getMessages();
}
+ /**
+ * {@inheritDoc}
+ */
public Throwable getThrowable(int index) {
return delegate.getThrowable(index);
}
+ /**
+ * {@inheritDoc}
+ */
public int getThrowableCount() {
return delegate.getThrowableCount();
}
+ /**
+ * {@inheritDoc}
+ */
public Throwable[] getThrowables() {
return delegate.getThrowables();
}
+ /**
+ * {@inheritDoc}
+ */
public int indexOfThrowable(Class type) {
return delegate.indexOfThrowable(type, 0);
}
+ /**
+ * {@inheritDoc}
+ */
public int indexOfThrowable(Class type, int fromIndex) {
return delegate.indexOfThrowable(type, fromIndex);
}
+ /**
+ * {@inheritDoc}
+ */
public void printStackTrace() {
delegate.printStackTrace();
}
+ /**
+ * {@inheritDoc}
+ */
public void printStackTrace(PrintStream out) {
delegate.printStackTrace(out);
}
+ /**
+ * {@inheritDoc}
+ */
public void printStackTrace(PrintWriter out) {
delegate.printStackTrace(out);
}
+ /**
+ * {@inheritDoc}
+ */
public final void printPartialStackTrace(PrintWriter out) {
super.printStackTrace(out);
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/NestableException.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/NestableException.java (.../NestableException.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/NestableException.java (.../NestableException.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,55 +1,18 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang.exception;
@@ -63,9 +26,9 @@
* about the exception which was caught and provoked throwing the
* current exception. Catching and rethrowing may occur multiple
* times, and provided that all exceptions except the first one
- * are descendands of NestedException
, when the
+ * are descendants of NestedException
, when the
* exception is finally printed out using any of the
- * printStackTrace()
methods, the stacktrace will contain
+ * printStackTrace()
methods, the stack trace will contain
* the information about all exceptions thrown and caught on
* the way.
* Running the following program
@@ -102,7 +65,7 @@
* 30 }
* 31 }
*
- *
Yields the following stacktrace:
+ *
Yields the following stack trace:
*
* org.apache.commons.lang.exception.NestableException: foo
* at Test.a(Test.java:16)
@@ -118,7 +81,7 @@
*
*
* @author Rafal Krzewski
- * @author Daniel Rall
+ * @author Daniel L. Rall
* @author Kasper Nielsen
* @author Steven Caswell
* @since 1.0
@@ -127,6 +90,13 @@
public class NestableException extends Exception implements Nestable {
/**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
* The helper instance which contains much of the code which we
* delegate to.
*/
@@ -181,6 +151,9 @@
this.cause = cause;
}
+ /**
+ * {@inheritDoc}
+ */
public Throwable getCause() {
return cause;
}
@@ -189,6 +162,8 @@
* Returns the detail message string of this throwable. If it was
* created with a null message, returns the following:
* (cause==null ? null : cause.toString()).
+ *
+ * @return String message string of the throwable
*/
public String getMessage() {
if (super.getMessage() != null) {
@@ -200,50 +175,82 @@
}
}
+ /**
+ * {@inheritDoc}
+ */
public String getMessage(int index) {
if (index == 0) {
return super.getMessage();
- } else {
- return delegate.getMessage(index);
}
+ return delegate.getMessage(index);
}
+ /**
+ * {@inheritDoc}
+ */
public String[] getMessages() {
return delegate.getMessages();
}
+ /**
+ * {@inheritDoc}
+ */
public Throwable getThrowable(int index) {
return delegate.getThrowable(index);
}
+ /**
+ * {@inheritDoc}
+ */
public int getThrowableCount() {
return delegate.getThrowableCount();
}
+ /**
+ * {@inheritDoc}
+ */
public Throwable[] getThrowables() {
return delegate.getThrowables();
}
+ /**
+ * {@inheritDoc}
+ */
public int indexOfThrowable(Class type) {
return delegate.indexOfThrowable(type, 0);
}
+ /**
+ * {@inheritDoc}
+ */
public int indexOfThrowable(Class type, int fromIndex) {
return delegate.indexOfThrowable(type, fromIndex);
}
+ /**
+ * {@inheritDoc}
+ */
public void printStackTrace() {
delegate.printStackTrace();
}
+ /**
+ * {@inheritDoc}
+ */
public void printStackTrace(PrintStream out) {
delegate.printStackTrace(out);
}
+ /**
+ * {@inheritDoc}
+ */
public void printStackTrace(PrintWriter out) {
delegate.printStackTrace(out);
}
+ /**
+ * {@inheritDoc}
+ */
public final void printPartialStackTrace(PrintWriter out) {
super.printStackTrace(out);
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/NestableRuntimeException.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/NestableRuntimeException.java (.../NestableRuntimeException.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/NestableRuntimeException.java (.../NestableRuntimeException.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,55 +1,18 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang.exception;
@@ -62,7 +25,7 @@
*
* @see org.apache.commons.lang.exception.NestableException
* @author Rafal Krzewski
- * @author Daniel Rall
+ * @author Daniel L. Rall
* @author Kasper Nielsen
* @author Steven Caswell
* @since 1.0
@@ -71,6 +34,13 @@
public class NestableRuntimeException extends RuntimeException implements Nestable {
/**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
* The helper instance which contains much of the code which we
* delegate to.
*/
@@ -125,6 +95,9 @@
this.cause = cause;
}
+ /**
+ * {@inheritDoc}
+ */
public Throwable getCause() {
return cause;
}
@@ -133,6 +106,8 @@
* Returns the detail message string of this throwable. If it was
* created with a null message, returns the following:
* (cause==null ? null : cause.toString()).
+ *
+ * @return String message string of the throwable
*/
public String getMessage() {
if (super.getMessage() != null) {
@@ -144,50 +119,82 @@
}
}
+ /**
+ * {@inheritDoc}
+ */
public String getMessage(int index) {
if (index == 0) {
return super.getMessage();
- } else {
- return delegate.getMessage(index);
}
+ return delegate.getMessage(index);
}
+ /**
+ * {@inheritDoc}
+ */
public String[] getMessages() {
return delegate.getMessages();
}
+ /**
+ * {@inheritDoc}
+ */
public Throwable getThrowable(int index) {
return delegate.getThrowable(index);
}
+ /**
+ * {@inheritDoc}
+ */
public int getThrowableCount() {
return delegate.getThrowableCount();
}
+ /**
+ * {@inheritDoc}
+ */
public Throwable[] getThrowables() {
return delegate.getThrowables();
}
+ /**
+ * {@inheritDoc}
+ */
public int indexOfThrowable(Class type) {
return delegate.indexOfThrowable(type, 0);
}
+ /**
+ * {@inheritDoc}
+ */
public int indexOfThrowable(Class type, int fromIndex) {
return delegate.indexOfThrowable(type, fromIndex);
}
+ /**
+ * {@inheritDoc}
+ */
public void printStackTrace() {
delegate.printStackTrace();
}
+ /**
+ * {@inheritDoc}
+ */
public void printStackTrace(PrintStream out) {
delegate.printStackTrace(out);
}
+ /**
+ * {@inheritDoc}
+ */
public void printStackTrace(PrintWriter out) {
delegate.printStackTrace(out);
}
+ /**
+ * {@inheritDoc}
+ */
public final void printPartialStackTrace(PrintWriter out) {
super.printStackTrace(out);
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/package.html
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/package.html (.../package.html) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/package.html (.../package.html) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,3 +1,19 @@
+
Provides JDK 1.4 style Nested Exception functionality for those on prior Java
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/math/DoubleRange.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/math/DoubleRange.java (.../DoubleRange.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/math/DoubleRange.java (.../DoubleRange.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,69 +1,39 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang.math;
import java.io.Serializable;
+import org.apache.commons.lang.text.StrBuilder;
+
/**
* DoubleRange
represents an inclusive range of double
s.
*
- * @author Stephen Colebourne
+ * @author Apache Software Foundation
* @since 2.0
* @version $Id$
*/
public final class DoubleRange extends Range implements Serializable {
+ /**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
private static final long serialVersionUID = 71849363892740L;
/**
@@ -343,7 +313,7 @@
* range by double
comparison
*/
public boolean containsDouble(double value) {
- return (value >= min && value <= max);
+ return value >= min && value <= max;
}
// Range tests
@@ -434,7 +404,7 @@
*/
public String toString() {
if (toString == null) {
- StringBuffer buf = new StringBuffer(32);
+ StrBuilder buf = new StrBuilder(32);
buf.append("Range[");
buf.append(min);
buf.append(',');
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/math/FloatRange.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/math/FloatRange.java (.../FloatRange.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/math/FloatRange.java (.../FloatRange.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,55 +1,18 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang.math;
@@ -58,12 +21,17 @@
/**
* FloatRange
represents an inclusive range of float
s.
*
- * @author Stephen Colebourne
+ * @author Apache Software Foundation
* @since 2.0
* @version $Id$
*/
public final class FloatRange extends Range implements Serializable {
+ /**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
private static final long serialVersionUID = 71849363892750L;
/**
@@ -339,7 +307,7 @@
* range by float
comparison
*/
public boolean containsFloat(float value) {
- return (value >= min && value <= max);
+ return value >= min && value <= max;
}
// Range tests
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/math/Fraction.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/math/Fraction.java (.../Fraction.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/math/Fraction.java (.../Fraction.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,77 +1,47 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang.math;
-import java.io.Serializable;
+import java.math.BigInteger;
+import org.apache.commons.lang.text.StrBuilder;
+
/**
* Fraction
is a Number
implementation that
* stores fractions accurately.
*
* This class is immutable, and interoperable with most methods that accept
* a Number
.
*
+ * @author Apache Software Foundation
* @author Travis Reeder
- * @author Stephen Colebourne
* @author Tim O'Brien
* @author Pete Gieser
+ * @author C. Scott Ananian
* @since 2.0
* @version $Id$
*/
-public final class Fraction extends Number implements Serializable, Comparable {
+public final class Fraction extends Number implements Comparable {
- /** Serialization lock, Lang version 2.0 */
+ /**
+ * Required for serialization support. Lang version 2.0.
+ *
+ * @see java.io.Serializable
+ */
private static final long serialVersionUID = 65382027393090L;
/**
@@ -175,6 +145,10 @@
throw new ArithmeticException("The denominator must not be zero");
}
if (denominator < 0) {
+ if (numerator==Integer.MIN_VALUE ||
+ denominator==Integer.MIN_VALUE) {
+ throw new ArithmeticException("overflow: can't negate");
+ }
numerator = -numerator;
denominator = -denominator;
}
@@ -192,7 +166,7 @@
* @param denominator the denominator, for example the seven in 'one and three sevenths'
* @return a new fraction instance
* @throws ArithmeticException if the denomiator is zero
- * @throws ArithmeticException if the denomiator is negative
+ * @throws ArithmeticException if the denominator is negative
* @throws ArithmeticException if the numerator is negative
* @throws ArithmeticException if the resulting numerator exceeds
* Integer.MAX_VALUE
@@ -207,39 +181,57 @@
if (numerator < 0) {
throw new ArithmeticException("The numerator must not be negative");
}
- double numeratorValue = 0;
+ long numeratorValue;
if (whole < 0) {
- numeratorValue = (double) whole * denominator - numerator;
+ numeratorValue = whole * (long)denominator - numerator;
} else {
- numeratorValue = (double) whole * denominator + numerator;
+ numeratorValue = whole * (long)denominator + numerator;
}
- if (Math.abs(numeratorValue) > Integer.MAX_VALUE) {
+ if (numeratorValue < Integer.MIN_VALUE ||
+ numeratorValue > Integer.MAX_VALUE) {
throw new ArithmeticException("Numerator too large to represent as an Integer.");
}
return new Fraction((int) numeratorValue, denominator);
}
/**
- * Creates a Fraction
instance with the 2 parts
+ *
Creates a reduced Fraction
instance with the 2 parts
* of a fraction Y/Z.
*
+ * For example, if the input parameters represent 2/4, then the created
+ * fraction will be 1/2.
+ *
* Any negative signs are resolved to be on the numerator.
*
* @param numerator the numerator, for example the three in 'three sevenths'
* @param denominator the denominator, for example the seven in 'three sevenths'
* @return a new fraction instance, with the numerator and denominator reduced
- * @throws ArithmeticException if the denomiator is zero
+ * @throws ArithmeticException if the denominator is zero
*/
public static Fraction getReducedFraction(int numerator, int denominator) {
if (denominator == 0) {
throw new ArithmeticException("The denominator must not be zero");
}
+ if (numerator==0) {
+ return ZERO; // normalize zero.
+ }
+ // allow 2^k/-2^31 as a valid fraction (where k>0)
+ if (denominator==Integer.MIN_VALUE && (numerator&1)==0) {
+ numerator/=2; denominator/=2;
+ }
if (denominator < 0) {
+ if (numerator==Integer.MIN_VALUE ||
+ denominator==Integer.MIN_VALUE) {
+ throw new ArithmeticException("overflow: can't negate");
+ }
numerator = -numerator;
denominator = -denominator;
}
- int gcd = greatestCommonDivisor(Math.abs(numerator), denominator);
- return new Fraction(numerator / gcd, denominator / gcd);
+ // simplify fraction.
+ int gcd = greatestCommonDivisor(numerator, denominator);
+ numerator /= gcd;
+ denominator /= gcd;
+ return new Fraction(numerator, denominator);
}
/**
@@ -253,7 +245,7 @@
* @return a new fraction instance that is close to the value
* @throws ArithmeticException if |value| > Integer.MAX_VALUE
* or value = NaN
- * @throws ArithmeticException if the calculated denomiator is zero
+ * @throws ArithmeticException if the calculated denominator is zero
* @throws ArithmeticException if the the algorithm does not converge
*/
public static Fraction getFraction(double value) {
@@ -313,11 +305,11 @@
*
* The formats accepted are:
*
- *
*
* double
String containing a dot
* - 'X Y/Z'
* - 'Y/Z'
+ * - 'X' (a simple whole number)
*
* and a .
*
@@ -345,11 +337,9 @@
if (pos < 0) {
throw new NumberFormatException("The fraction could not be parsed as the format X Y/Z");
} else {
+ int numer = Integer.parseInt(str.substring(0, pos));
int denom = Integer.parseInt(str.substring(pos + 1));
- return getFraction(
- Integer.parseInt(str.substring(0, pos)) + whole * denom,
- denom
- );
+ return getFraction(whole, numer, denom);
}
}
@@ -359,10 +349,9 @@
// simple whole number
return getFraction(Integer.parseInt(str), 1);
} else {
- return getFraction(
- Integer.parseInt(str.substring(0, pos)),
- Integer.parseInt(str.substring(pos + 1))
- );
+ int numer = Integer.parseInt(str.substring(0, pos));
+ int denom = Integer.parseInt(str.substring(pos + 1));
+ return getFraction(numer, denom);
}
}
@@ -468,28 +457,45 @@
/**
* Reduce the fraction to the smallest values for the numerator and
- * denominator, returning the result..
+ * denominator, returning the result.
+ *
+ * For example, if this fraction represents 2/4, then the result
+ * will be 1/2.
*
- * @return a new reduce fraction instance, or this if no simplification possible
+ * @return a new reduced fraction instance, or this if no simplification possible
*/
public Fraction reduce() {
+ if (numerator == 0) {
+ return equals(ZERO) ? this : ZERO;
+ }
int gcd = greatestCommonDivisor(Math.abs(numerator), denominator);
+ if (gcd == 1) {
+ return this;
+ }
return Fraction.getFraction(numerator / gcd, denominator / gcd);
}
/**
- * Gets a fraction that is the invert (1/fraction) of this one.
- *
+ * Gets a fraction that is the inverse (1/fraction) of this one.
+ *
* The returned fraction is not reduced.
*
- * @return a new fraction instance with the numerator and denominator inverted
- * @throws ArithmeticException if the numerator is zero
+ * @return a new fraction instance with the numerator and denominator
+ * inverted.
+ * @throws ArithmeticException if the fraction represents zero.
*/
public Fraction invert() {
if (numerator == 0) {
- throw new ArithmeticException("Unable to invert a fraction with a zero numerator");
+ throw new ArithmeticException("Unable to invert zero.");
}
- return getFraction(denominator, numerator);
+ if (numerator==Integer.MIN_VALUE) {
+ throw new ArithmeticException("overflow: can't negate numerator");
+ }
+ if (numerator<0) {
+ return new Fraction(-denominator, -numerator);
+ } else {
+ return new Fraction(denominator, numerator);
+ }
}
/**
@@ -500,12 +506,16 @@
* @return a new fraction instance with the opposite signed numerator
*/
public Fraction negate() {
- return getFraction(-numerator, denominator);
+ // the positive range is one smaller than the negative range of an int.
+ if (numerator==Integer.MIN_VALUE) {
+ throw new ArithmeticException("overflow: too large to negate");
+ }
+ return new Fraction(-numerator, denominator);
}
/**
* Gets a fraction that is the positive equivalent of this one.
- * More precisely:
(fraction >= 0 ? this : -fraction)
+ * More precisely: (fraction >= 0 ? this : -fraction)
*
* The returned fraction is not reduced.
*
@@ -516,13 +526,13 @@
if (numerator >= 0) {
return this;
}
- return getFraction(-numerator, denominator);
+ return negate();
}
/**
* Gets a fraction that is raised to the passed in power.
*
- * The returned fraction is not reduced.
+ * The returned fraction is in reduced form.
*
* @param power the power to raise the fraction to
* @return this
if the power is one, ONE
if the power
@@ -536,44 +546,153 @@
return this;
} else if (power == 0) {
return ONE;
+ } else if (power < 0) {
+ if (power==Integer.MIN_VALUE) { // MIN_VALUE can't be negated.
+ return this.invert().pow(2).pow(-(power/2));
+ }
+ return this.invert().pow(-power);
} else {
- double denominatorValue = Math.pow(denominator, power);
- double numeratorValue = Math.pow(numerator, power);
- if (numeratorValue > Integer.MAX_VALUE || denominatorValue > Integer.MAX_VALUE) {
- throw new ArithmeticException("Integer overflow");
+ Fraction f = this.multiplyBy(this);
+ if ((power % 2) == 0) { // if even...
+ return f.pow(power/2);
+ } else { // if odd...
+ return f.pow(power/2).multiplyBy(this);
}
- if (power < 0) {
- return getFraction((int) Math.pow(denominator, -power),
- (int) Math.pow(numerator, -power));
- }
- return getFraction((int) Math.pow(numerator, power),
- (int) Math.pow(denominator, power));
}
}
/**
- * Gets the greatest common divisor of two numbers.
+ * Gets the greatest common divisor of the absolute value of
+ * two numbers, using the "binary gcd" method which avoids
+ * division and modulo operations. See Knuth 4.5.2 algorithm B.
+ * This algorithm is due to Josef Stein (1961).
*
- * @param number1 a positive number
- * @param number2 a positive number
+ * @param u a non-zero number
+ * @param v a non-zero number
* @return the greatest common divisor, never zero
*/
- private static int greatestCommonDivisor(int number1, int number2) {
- int remainder = number1 % number2;
- while (remainder != 0) {
- number1 = number2;
- number2 = remainder;
- remainder = number1 % number2;
+ private static int greatestCommonDivisor(int u, int v) {
+ //if either op. is abs 0 or 1, return 1:
+ if (Math.abs(u) <= 1 || Math.abs(v) <= 1) {
+ return 1;
}
- return number2;
+ // keep u and v negative, as negative integers range down to
+ // -2^31, while positive numbers can only be as large as 2^31-1
+ // (i.e. we can't necessarily negate a negative number without
+ // overflow)
+ if (u>0) { u=-u; } // make u negative
+ if (v>0) { v=-v; } // make v negative
+ // B1. [Find power of 2]
+ int k=0;
+ while ((u&1)==0 && (v&1)==0 && k<31) { // while u and v are both even...
+ u/=2; v/=2; k++; // cast out twos.
+ }
+ if (k==31) {
+ throw new ArithmeticException("overflow: gcd is 2^31");
+ }
+ // B2. Initialize: u and v have been divided by 2^k and at least
+ // one is odd.
+ int t = ((u&1)==1) ? v : -(u/2)/*B3*/;
+ // t negative: u was odd, v may be even (t replaces v)
+ // t positive: u was even, v is odd (t replaces u)
+ do {
+ /* assert u<0 && v<0; */
+ // B4/B3: cast out twos from t.
+ while ((t&1)==0) { // while t is even..
+ t/=2; // cast out twos
+ }
+ // B5 [reset max(u,v)]
+ if (t>0) {
+ u = -t;
+ } else {
+ v = t;
+ }
+ // B6/B3. at this point both u and v should be odd.
+ t = (v - u)/2;
+ // |u| larger: t positive (replace u)
+ // |v| larger: t negative (replace v)
+ } while (t!=0);
+ return -u*(1<x*y
+ * @throws ArithmeticException if the result can not be represented as
+ * an int
+ */
+ private static int mulAndCheck(int x, int y) {
+ long m = ((long)x)*((long)y);
+ if (m < Integer.MIN_VALUE ||
+ m > Integer.MAX_VALUE) {
+ throw new ArithmeticException("overflow: mul");
+ }
+ return (int)m;
+ }
+
/**
- * Adds the value of this fraction to another, returning the result in
- * reduced form.
+ * Multiply two non-negative integers, checking for overflow.
+ *
+ * @param x a non-negative factor
+ * @param y a non-negative factor
+ * @return the product x*y
+ * @throws ArithmeticException if the result can not be represented as
+ * an int
+ */
+ private static int mulPosAndCheck(int x, int y) {
+ /* assert x>=0 && y>=0; */
+ long m = ((long)x)*((long)y);
+ if (m > Integer.MAX_VALUE) {
+ throw new ArithmeticException("overflow: mulPos");
+ }
+ return (int)m;
+ }
+
+ /**
+ * Add two integers, checking for overflow.
+ *
+ * @param x an addend
+ * @param y an addend
+ * @return the sum x+y
+ * @throws ArithmeticException if the result can not be represented as
+ * an int
+ */
+ private static int addAndCheck(int x, int y) {
+ long s = (long)x+(long)y;
+ if (s < Integer.MIN_VALUE ||
+ s > Integer.MAX_VALUE) {
+ throw new ArithmeticException("overflow: add");
+ }
+ return (int)s;
+ }
+
+ /**
+ * Subtract two integers, checking for overflow.
+ *
+ * @param x the minuend
+ * @param y the subtrahend
+ * @return the difference x-y
+ * @throws ArithmeticException if the result can not be represented as
+ * an int
+ */
+ private static int subAndCheck(int x, int y) {
+ long s = (long)x-(long)y;
+ if (s < Integer.MIN_VALUE ||
+ s > Integer.MAX_VALUE) {
+ throw new ArithmeticException("overflow: add");
+ }
+ return (int)s;
+ }
+
+ /**
+ * Adds the value of this fraction to another, returning the result in reduced form.
+ * The algorithm follows Knuth, 4.5.1.
*
* @param fraction the fraction to add, must not be null
* @return a Fraction
instance with the resulting values
@@ -582,50 +701,84 @@
* Integer.MAX_VALUE
*/
public Fraction add(Fraction fraction) {
- if (fraction == null) {
- throw new IllegalArgumentException("The fraction must not be null");
- }
- if (numerator == 0) {
- return fraction;
- }
- if (fraction.numerator == 0) {
- return this;
- }
- // Compute lcd explicitly to limit overflow
- int gcd = greatestCommonDivisor(Math.abs(fraction.denominator), Math.abs(denominator));
- int thisResidue = denominator/gcd;
- int thatResidue = fraction.denominator/gcd;
- double denominatorValue = Math.abs((double) gcd * thisResidue * thatResidue);
- double numeratorValue = (double) numerator * thatResidue + fraction.numerator * thisResidue;
- if (Math.abs(numeratorValue) > Integer.MAX_VALUE ||
- Math.abs(denominatorValue) > Integer.MAX_VALUE) {
- throw new ArithmeticException("Integer overflow");
- }
- return Fraction.getReducedFraction((int) numeratorValue, (int) denominatorValue);
+ return addSub(fraction, true /* add */);
}
/**
- * Subtracts the value of another fraction from the value of this one,
+ *
Subtracts the value of another fraction from the value of this one,
* returning the result in reduced form.
*
* @param fraction the fraction to subtract, must not be null
* @return a Fraction
instance with the resulting values
* @throws IllegalArgumentException if the fraction is null
- * @throws ArithmeticException if the resulting numerator or denominator exceeds
- * Integer.MAX_VALUE
+ * @throws ArithmeticException if the resulting numerator or denominator
+ * cannot be represented in an int
.
*/
public Fraction subtract(Fraction fraction) {
+ return addSub(fraction, false /* subtract */);
+ }
+
+ /**
+ * Implement add and subtract using algorithm described in Knuth 4.5.1.
+ *
+ * @param fraction the fraction to subtract, must not be null
+ * @param isAdd true to add, false to subtract
+ * @return a Fraction
instance with the resulting values
+ * @throws IllegalArgumentException if the fraction is null
+ * @throws ArithmeticException if the resulting numerator or denominator
+ * cannot be represented in an int
.
+ */
+ private Fraction addSub(Fraction fraction, boolean isAdd) {
if (fraction == null) {
throw new IllegalArgumentException("The fraction must not be null");
}
- return add(fraction.negate());
+ // zero is identity for addition.
+ if (numerator == 0) {
+ return isAdd ? fraction : fraction.negate();
+ }
+ if (fraction.numerator == 0) {
+ return this;
+ }
+ // if denominators are randomly distributed, d1 will be 1 about 61%
+ // of the time.
+ int d1 = greatestCommonDivisor(denominator, fraction.denominator);
+ if (d1==1) {
+ // result is ( (u*v' +/- u'v) / u'v')
+ int uvp = mulAndCheck(numerator, fraction.denominator);
+ int upv = mulAndCheck(fraction.numerator, denominator);
+ return new Fraction
+ (isAdd ? addAndCheck(uvp, upv) : subAndCheck(uvp, upv),
+ mulPosAndCheck(denominator, fraction.denominator));
+ }
+ // the quantity 't' requires 65 bits of precision; see knuth 4.5.1
+ // exercise 7. we're going to use a BigInteger.
+ // t = u(v'/d1) +/- v(u'/d1)
+ BigInteger uvp = BigInteger.valueOf(numerator)
+ .multiply(BigInteger.valueOf(fraction.denominator/d1));
+ BigInteger upv = BigInteger.valueOf(fraction.numerator)
+ .multiply(BigInteger.valueOf(denominator/d1));
+ BigInteger t = isAdd ? uvp.add(upv) : uvp.subtract(upv);
+ // but d2 doesn't need extra precision because
+ // d2 = gcd(t,d1) = gcd(t mod d1, d1)
+ int tmodd1 = t.mod(BigInteger.valueOf(d1)).intValue();
+ int d2 = (tmodd1==0)?d1:greatestCommonDivisor(tmodd1, d1);
+
+ // result is (t/d2) / (u'/d1)(v'/d2)
+ BigInteger w = t.divide(BigInteger.valueOf(d2));
+ if (w.bitLength() > 31) {
+ throw new ArithmeticException
+ ("overflow: numerator too large after multiply");
+ }
+ return new Fraction
+ (w.intValue(),
+ mulPosAndCheck(denominator/d1, fraction.denominator/d2));
}
/**
- * Multiplies the value of this fraction by another, returning the result
- * in reduced form.
+ * Multiplies the value of this fraction by another, returning the
+ * result in reduced form.
*
- * @param fraction the fraction to multipy by, must not be null
+ * @param fraction the fraction to multiply by, must not be null
* @return a Fraction
instance with the resulting values
* @throws IllegalArgumentException if the fraction is null
* @throws ArithmeticException if the resulting numerator or denominator exceeds
@@ -638,18 +791,17 @@
if (numerator == 0 || fraction.numerator == 0) {
return ZERO;
}
- double numeratorValue = (double) numerator * fraction.numerator;
- double denominatorValue = (double) denominator * fraction.denominator;
- if (Math.abs(numeratorValue) > Integer.MAX_VALUE ||
- Math.abs(denominatorValue) > Integer.MAX_VALUE) {
- throw new ArithmeticException("Integer overflow");
- }
- return getReducedFraction((int) numeratorValue, (int) denominatorValue);
+ // knuth 4.5.1
+ // make sure we don't overflow unless the result *must* overflow.
+ int d1 = greatestCommonDivisor(numerator, fraction.denominator);
+ int d2 = greatestCommonDivisor(fraction.numerator, denominator);
+ return getReducedFraction
+ (mulAndCheck(numerator/d1, fraction.numerator/d2),
+ mulPosAndCheck(denominator/d2, fraction.denominator/d1));
}
/**
- * Divide the value of this fraction by another, returning the result
- * in reduced form.
+ * Divide the value of this fraction by another.
*
* @param fraction the fraction to divide by, must not be null
* @return a Fraction
instance with the resulting values
@@ -665,16 +817,7 @@
if (fraction.numerator == 0) {
throw new ArithmeticException("The fraction to divide by must not be zero");
}
- if (numerator == 0) {
- return ZERO;
- }
- double numeratorValue = (double) numerator * fraction.denominator;
- double denominatorValue = (double) denominator * fraction.numerator;
- if (Math.abs(numeratorValue) > Integer.MAX_VALUE ||
- Math.abs(denominatorValue) > Integer.MAX_VALUE) {
- throw new ArithmeticException("Integer overflow");
- }
- return getReducedFraction((int) numeratorValue, (int) denominatorValue);
+ return multiplyBy(fraction.invert());
}
// Basics
@@ -696,8 +839,8 @@
return false;
}
Fraction other = (Fraction) obj;
- return (numerator == other.numerator &&
- denominator == other.denominator);
+ return (getNumerator() == other.getNumerator() &&
+ getDenominator() == other.getDenominator());
}
/**
@@ -707,23 +850,29 @@
*/
public int hashCode() {
if (hashCode == 0) {
- hashCode = 17;
- hashCode = 37 * hashCode + numerator;
- hashCode = 37 * hashCode + denominator;
+ // hashcode update should be atomic.
+ hashCode = 37 * (37 * 17 + getNumerator()) + getDenominator();
}
return hashCode;
}
/**
* Compares this object to another based on size.
*
+ * Note: this class has a natural ordering that is inconsistent
+ * with equals, because, for example, equals treats 1/2 and 2/4 as
+ * different, whereas compareTo treats them as equal.
+ *
* @param object the object to compare to
* @return -1 if this is less, 0 if equal, +1 if greater
* @throws ClassCastException if the object is not a Fraction
* @throws NullPointerException if the object is null
*/
public int compareTo(Object object) {
Fraction other = (Fraction) object;
+ if (this==other) {
+ return 0;
+ }
if (numerator == other.numerator && denominator == other.denominator) {
return 0;
}
@@ -749,10 +898,10 @@
*/
public String toString() {
if (toString == null) {
- toString = new StringBuffer(32)
- .append(numerator)
+ toString = new StrBuilder(32)
+ .append(getNumerator())
.append('/')
- .append(denominator).toString();
+ .append(getDenominator()).toString();
}
return toString;
}
@@ -772,23 +921,28 @@
toProperString = "0";
} else if (numerator == denominator) {
toProperString = "1";
- } else if (Math.abs(numerator) > denominator) {
+ } else if (numerator == -1 * denominator) {
+ toProperString = "-1";
+ } else if ((numerator>0?-numerator:numerator) < -denominator) {
+ // note that we do the magnitude comparison test above with
+ // NEGATIVE (not positive) numbers, since negative numbers
+ // have a larger range. otherwise numerator==Integer.MIN_VALUE
+ // is handled incorrectly.
int properNumerator = getProperNumerator();
if (properNumerator == 0) {
toProperString = Integer.toString(getProperWhole());
} else {
- toProperString = new StringBuffer(32)
+ toProperString = new StrBuilder(32)
.append(getProperWhole()).append(' ')
.append(properNumerator).append('/')
- .append(denominator).toString();
+ .append(getDenominator()).toString();
}
} else {
- toProperString = new StringBuffer(32)
- .append(numerator).append('/')
- .append(denominator).toString();
+ toProperString = new StrBuilder(32)
+ .append(getNumerator()).append('/')
+ .append(getDenominator()).toString();
}
}
return toProperString;
}
-
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/math/IEEE754rUtils.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/math/IEEE754rUtils.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/math/IEEE754rUtils.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,266 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang.math;
+
+/**
+ *
Provides IEEE-754r variants of NumberUtils methods.
+ *
+ * See: http://en.wikipedia.org/wiki/IEEE_754r
+ *
+ * @since 2.4
+ * @author Apache Software Foundation
+ * @version $Id$
+ */
+public class IEEE754rUtils {
+
+ /**
+ * Returns the minimum value in an array.
+ *
+ * @param array an array, must not be null or empty
+ * @return the minimum value in the array
+ * @throws IllegalArgumentException if array
is null
+ * @throws IllegalArgumentException if array
is empty
+ */
+ public static double min(double[] array) {
+ // Validates input
+ if (array == null) {
+ throw new IllegalArgumentException("The Array must not be null");
+ } else if (array.length == 0) {
+ throw new IllegalArgumentException("Array cannot be empty.");
+ }
+
+ // Finds and returns min
+ double min = array[0];
+ for (int i = 1; i < array.length; i++) {
+ min = min(array[i], min);
+ }
+
+ return min;
+ }
+
+ /**
+ * Returns the minimum value in an array.
+ *
+ * @param array an array, must not be null or empty
+ * @return the minimum value in the array
+ * @throws IllegalArgumentException if array
is null
+ * @throws IllegalArgumentException if array
is empty
+ */
+ public static float min(float[] array) {
+ // Validates input
+ if (array == null) {
+ throw new IllegalArgumentException("The Array must not be null");
+ } else if (array.length == 0) {
+ throw new IllegalArgumentException("Array cannot be empty.");
+ }
+
+ // Finds and returns min
+ float min = array[0];
+ for (int i = 1; i < array.length; i++) {
+ min = min(array[i], min);
+ }
+
+ return min;
+ }
+
+ /**
+ * Gets the minimum of three double
values.
+ *
+ * NaN is only returned if all numbers are NaN as per IEEE-754r.
+ *
+ * @param a value 1
+ * @param b value 2
+ * @param c value 3
+ * @return the smallest of the values
+ */
+ public static double min(double a, double b, double c) {
+ return min(min(a, b), c);
+ }
+
+ /**
+ * Gets the minimum of two double
values.
+ *
+ * NaN is only returned if all numbers are NaN as per IEEE-754r.
+ *
+ * @param a value 1
+ * @param b value 2
+ * @return the smallest of the values
+ */
+ public static double min(double a, double b) {
+ if(Double.isNaN(a)) {
+ return b;
+ } else
+ if(Double.isNaN(b)) {
+ return a;
+ } else {
+ return Math.min(a, b);
+ }
+ }
+
+ /**
+ * Gets the minimum of three float
values.
+ *
+ * NaN is only returned if all numbers are NaN as per IEEE-754r.
+ *
+ * @param a value 1
+ * @param b value 2
+ * @param c value 3
+ * @return the smallest of the values
+ */
+ public static float min(float a, float b, float c) {
+ return min(min(a, b), c);
+ }
+
+ /**
+ * Gets the minimum of two float
values.
+ *
+ * NaN is only returned if all numbers are NaN as per IEEE-754r.
+ *
+ * @param a value 1
+ * @param b value 2
+ * @return the smallest of the values
+ */
+ public static float min(float a, float b) {
+ if(Float.isNaN(a)) {
+ return b;
+ } else
+ if(Float.isNaN(b)) {
+ return a;
+ } else {
+ return Math.min(a, b);
+ }
+ }
+
+ /**
+ * Returns the maximum value in an array.
+ *
+ * @param array an array, must not be null or empty
+ * @return the minimum value in the array
+ * @throws IllegalArgumentException if array
is null
+ * @throws IllegalArgumentException if array
is empty
+ */
+ public static double max(double[] array) {
+ // Validates input
+ if (array== null) {
+ throw new IllegalArgumentException("The Array must not be null");
+ } else if (array.length == 0) {
+ throw new IllegalArgumentException("Array cannot be empty.");
+ }
+
+ // Finds and returns max
+ double max = array[0];
+ for (int j = 1; j < array.length; j++) {
+ max = max(array[j], max);
+ }
+
+ return max;
+ }
+
+ /**
+ * Returns the maximum value in an array.
+ *
+ * @param array an array, must not be null or empty
+ * @return the minimum value in the array
+ * @throws IllegalArgumentException if array
is null
+ * @throws IllegalArgumentException if array
is empty
+ */
+ public static float max(float[] array) {
+ // Validates input
+ if (array == null) {
+ throw new IllegalArgumentException("The Array must not be null");
+ } else if (array.length == 0) {
+ throw new IllegalArgumentException("Array cannot be empty.");
+ }
+
+ // Finds and returns max
+ float max = array[0];
+ for (int j = 1; j < array.length; j++) {
+ max = max(array[j], max);
+ }
+
+ return max;
+ }
+
+ /**
+ * Gets the maximum of three double
values.
+ *
+ * NaN is only returned if all numbers are NaN as per IEEE-754r.
+ *
+ * @param a value 1
+ * @param b value 2
+ * @param c value 3
+ * @return the largest of the values
+ */
+ public static double max(double a, double b, double c) {
+ return max(max(a, b), c);
+ }
+
+ /**
+ * Gets the maximum of two double
values.
+ *
+ * NaN is only returned if all numbers are NaN as per IEEE-754r.
+ *
+ * @param a value 1
+ * @param b value 2
+ * @return the largest of the values
+ */
+ public static double max(double a, double b) {
+ if(Double.isNaN(a)) {
+ return b;
+ } else
+ if(Double.isNaN(b)) {
+ return a;
+ } else {
+ return Math.max(a, b);
+ }
+ }
+
+ /**
+ * Gets the maximum of three float
values.
+ *
+ * NaN is only returned if all numbers are NaN as per IEEE-754r.
+ *
+ * @param a value 1
+ * @param b value 2
+ * @param c value 3
+ * @return the largest of the values
+ */
+ public static float max(float a, float b, float c) {
+ return max(max(a, b), c);
+ }
+
+ /**
+ * Gets the maximum of two float
values.
+ *
+ * NaN is only returned if all numbers are NaN as per IEEE-754r.
+ *
+ * @param a value 1
+ * @param b value 2
+ * @return the largest of the values
+ */
+ public static float max(float a, float b) {
+ if(Float.isNaN(a)) {
+ return b;
+ } else
+ if(Float.isNaN(b)) {
+ return a;
+ } else {
+ return Math.max(a, b);
+ }
+ }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/math/IntRange.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/math/IntRange.java (.../IntRange.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/math/IntRange.java (.../IntRange.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,69 +1,39 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang.math;
import java.io.Serializable;
+import org.apache.commons.lang.text.StrBuilder;
+
/**
* IntRange
represents an inclusive range of int
s.
*
- * @author Stephen Colebourne
+ * @author Apache Software Foundation
* @since 2.0
* @version $Id$
*/
public final class IntRange extends Range implements Serializable {
+ /**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
private static final long serialVersionUID = 71849363892730L;
/**
@@ -314,7 +284,7 @@
* range by int
comparison
*/
public boolean containsInteger(int value) {
- return (value >= min && value <= max);
+ return value >= min && value <= max;
}
// Range tests
@@ -375,7 +345,7 @@
return false;
}
IntRange range = (IntRange) obj;
- return (min == range.min && max == range.max);
+ return min == range.min && max == range.max;
}
/**
@@ -402,7 +372,7 @@
*/
public String toString() {
if (toString == null) {
- StringBuffer buf = new StringBuffer(32);
+ StrBuilder buf = new StrBuilder(32);
buf.append("Range[");
buf.append(min);
buf.append(',');
@@ -413,4 +383,18 @@
return toString;
}
+ /**
+ * Returns an array containing all the integer values in the range.
+ *
+ * @return the int[]
representation of this range
+ * @since 2.4
+ */
+ public int[] toArray() {
+ int[] array = new int[max - min + 1];
+ for (int i = 0; i < array.length; i++) {
+ array[i] = min + i;
+ }
+
+ return array;
+ }
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/math/JVMRandom.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/math/JVMRandom.java (.../JVMRandom.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/math/JVMRandom.java (.../JVMRandom.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,55 +1,20 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
*
- * Copyright (c) 2002 The Apache Software Foundation. All rights
- * reserved.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+ * 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.
*/
package org.apache.commons.lang.math;
@@ -59,24 +24,47 @@
* JVMRandom
is a wrapper that supports all possible
* Random methods via the {@link java.lang.Math#random()} method
* and its system-wide {@link Random} object.
+ *
+ * It does this to allow for a Random class in which the seed is
+ * shared between all members of the class - a better name would
+ * have been SharedSeedRandom.
+ *
+ * N.B. the current implementation overrides the methods
+ * {@link Random#nextInt(int)} and {@link Random#nextLong()}
+ * to produce positive numbers ranging from 0 (inclusive)
+ * to MAX_VALUE (exclusive).
*
- * @author Henri Yandell
* @since 2.0
* @version $Id$
*/
public final class JVMRandom extends Random {
/**
- * Ensures that only the constructor can call reseed.
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
*/
+ private static final long serialVersionUID = 1L;
+
+ private static final Random SHARED_RANDOM = new Random();
+
+ /**
+ * Ensures that only the parent constructor can call reseed.
+ */
private boolean constructed = false;
+ /**
+ * Constructs a new instance.
+ */
public JVMRandom() {
this.constructed = true;
}
/**
* Unsupported in 2.0.
+ *
+ * @param seed ignored
+ * @throws UnsupportedOperationException
*/
public synchronized void setSeed(long seed) {
if (this.constructed) {
@@ -86,13 +74,19 @@
/**
* Unsupported in 2.0.
+ *
+ * @return Nothing, this method always throws an UnsupportedOperationException.
+ * @throws UnsupportedOperationException
*/
public synchronized double nextGaussian() {
throw new UnsupportedOperationException();
}
/**
* Unsupported in 2.0.
+ *
+ * @param byteArray ignored
+ * @throws UnsupportedOperationException
*/
public void nextBytes(byte[] byteArray) {
throw new UnsupportedOperationException();
@@ -101,12 +95,16 @@
/**
*
Returns the next pseudorandom, uniformly distributed int value
* from the Math.random() sequence.
- *
+ * Identical to nextInt(Integer.MAX_VALUE)
+ *
+ * N.B. All values are >= 0.
+ *
* @return the random int
*/
public int nextInt() {
return nextInt(Integer.MAX_VALUE);
}
+
/**
* Returns a pseudorandom, uniformly distributed int value between
* 0
(inclusive) and the specified value (exclusive), from
@@ -117,21 +115,19 @@
* @throws IllegalArgumentException when n <= 0
*/
public int nextInt(int n) {
- if (n <= 0) {
- throw new IllegalArgumentException(
- "Upper bound for nextInt must be positive"
- );
- }
- // TODO: check this cannot return 'n'
- return (int)(Math.random() * n);
+ return SHARED_RANDOM.nextInt(n);
}
+
/**
*
Returns the next pseudorandom, uniformly distributed long value
* from the Math.random() sequence.
+ * Identical to nextLong(Long.MAX_VALUE)
+ *
+ * N.B. All values are >= 0.
+ *
* @return the random long
*/
public long nextLong() {
- // possible loss of precision?
return nextLong(Long.MAX_VALUE);
}
@@ -151,8 +147,20 @@
"Upper bound for nextInt must be positive"
);
}
- // TODO: check this cannot return 'n'
- return (long)(Math.random() * n);
+ // Code adapted from Harmony Random#nextInt(int)
+ if ((n & -n) == n) { // n is power of 2
+ // dropping lower order bits improves behaviour for low values of n
+ return next63bits() >> 63 // drop all the bits
+ - bitsRequired(n-1); // except the ones we need
+ }
+ // Not a power of two
+ long val;
+ long bits;
+ do { // reject some values to improve distribution
+ bits = next63bits();
+ val = bits % n;
+ } while (bits - val + (n - 1) < 0);
+ return val;
}
/**
@@ -162,8 +170,9 @@
* @return the random boolean
*/
public boolean nextBoolean() {
- return (Math.random() > 0.5);
+ return SHARED_RANDOM.nextBoolean();
}
+
/**
* Returns the next pseudorandom, uniformly distributed float value
* between 0.0
and 1.0
from the Math.random()
@@ -172,15 +181,48 @@
* @return the random float
*/
public float nextFloat() {
- return (float)Math.random();
+ return SHARED_RANDOM.nextFloat();
}
+
/**
*
Synonymous to the Math.random() call.
*
* @return the random double
*/
public double nextDouble() {
- return Math.random();
+ return SHARED_RANDOM.nextDouble();
}
+ /**
+ * Get the next unsigned random long
+ * @return unsigned random long
+ */
+ private static long next63bits(){
+ // drop the sign bit to leave 63 random bits
+ return SHARED_RANDOM.nextLong() & 0x7fffffffffffffffL;
+ }
+
+ /**
+ * Count the number of bits required to represent a long number.
+ *
+ * @param num long number
+ * @return number of bits required
+ */
+ private static int bitsRequired(long num){
+ // Derived from Hacker's Delight, Figure 5-9
+ long y=num; // for checking right bits
+ int n=0; // number of leading zeros found
+ while(true){
+ // 64 = number of bits in a long
+ if (num < 0) {
+ return 64-n; // no leading zeroes left
+ }
+ if (y == 0) {
+ return n; // no bits left to check
+ }
+ n++;
+ num=num << 1; // check leading bits
+ y=y >> 1; // check trailing bits
+ }
+ }
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/math/LongRange.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/math/LongRange.java (.../LongRange.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/math/LongRange.java (.../LongRange.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,69 +1,39 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang.math;
import java.io.Serializable;
+import org.apache.commons.lang.text.StrBuilder;
+
/**
* LongRange
represents an inclusive range of long
s.
*
- * @author Stephen Colebourne
+ * @author Apache Software Foundation
* @since 2.0
* @version $Id$
*/
public final class LongRange extends Range implements Serializable {
+ /**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
private static final long serialVersionUID = 71849363892720L;
/**
@@ -264,9 +234,11 @@
}
/**
- * Gets the maximum number in this range as a int
.
+ * Gets the maximum number in this range cast to an int
.
*
* This conversion can lose information for large values.
+ *
+ * @return the maximum number in this range cast to an int
.
*/
public int getMaximumInteger() {
return (int) max;
@@ -276,6 +248,8 @@
* Gets the maximum number in this range as a double
.
*
* This conversion can lose information for large values.
+ *
+ * @return The maximum number in this range as a double
.
*/
public double getMaximumDouble() {
return max;
@@ -285,6 +259,8 @@
* Gets the maximum number in this range as a float
.
*
* This conversion can lose information for large values.
+ *
+ * @return The maximum number in this range as a float
.
*/
public float getMaximumFloat() {
return max;
@@ -321,7 +297,7 @@
* range by long
comparison
*/
public boolean containsLong(long value) {
- return (value >= min && value <= max);
+ return value >= min && value <= max;
}
// Range tests
@@ -382,7 +358,7 @@
return false;
}
LongRange range = (LongRange) obj;
- return (min == range.min && max == range.max);
+ return min == range.min && max == range.max;
}
/**
@@ -409,7 +385,7 @@
*/
public String toString() {
if (toString == null) {
- StringBuffer buf = new StringBuffer(32);
+ StrBuilder buf = new StrBuilder(32);
buf.append("Range[");
buf.append(min);
buf.append(',');
@@ -420,4 +396,18 @@
return toString;
}
+ /**
+ * Returns an array containing all the long values in the range.
+ *
+ * @return the long[]
representation of this range
+ * @since 2.4
+ */
+ public long[] toArray() {
+ long[] array = new long[(int)(max - min + 1L)];
+ for(int i = 0; i < array.length; i++) {
+ array[i] = min + i;
+ }
+ return array;
+ }
+
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/math/NumberRange.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/math/NumberRange.java (.../NumberRange.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/math/NumberRange.java (.../NumberRange.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,71 +1,41 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang.math;
import java.io.Serializable;
+import org.apache.commons.lang.text.StrBuilder;
+
/**
* NumberRange
represents an inclusive range of
* {@link java.lang.Number} objects of the same type.
*
+ * @author Apache Software Foundation
* @author Christopher Elkins
- * @author Stephen Colebourne
* @since 2.0 (previously in org.apache.commons.lang)
* @version $Id$
*/
public final class NumberRange extends Range implements Serializable {
+ /**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
private static final long serialVersionUID = 71849363892710L;
/**
@@ -207,7 +177,7 @@
}
int compareMin = ((Comparable) min).compareTo(number);
int compareMax = ((Comparable) max).compareTo(number);
- return (compareMin <= 0 && compareMax >= 0);
+ return compareMin <= 0 && compareMax >= 0;
}
// Range tests
@@ -260,7 +230,7 @@
*/
public String toString() {
if (toString == null) {
- StringBuffer buf = new StringBuffer(32);
+ StrBuilder buf = new StrBuilder(32);
buf.append("Range[");
buf.append(min);
buf.append(',');
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/math/NumberUtils.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/math/NumberUtils.java (.../NumberUtils.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/math/NumberUtils.java (.../NumberUtils.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,55 +1,18 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang.math;
@@ -61,14 +24,14 @@
/**
* Provides extra functionality for Java Number classes.
*
- * @author Henri Yandell
+ * @author Apache Software Foundation
* @author Rand McNeely
- * @author Stephen Colebourne
* @author Steve Downey
* @author Eric Pugh
* @author Phil Steitz
* @author Matthew Hawthorne
* @author Gary Gregory
+ * @author Fredrik Westermarck
* @since 2.0
* @version $Id$
*/
@@ -113,12 +76,13 @@
/**
* NumberUtils
instances should NOT be constructed in standard programming.
- * Instead, the class should be used as NumberUtils.stringToInt("6");
.
+ * Instead, the class should be used as NumberUtils.toInt("6");
.
*
* This constructor is public to permit tools that require a JavaBean instance
* to operate.
*/
public NumberUtils() {
+ super();
}
//-----------------------------------------------------------------------
@@ -128,32 +92,345 @@
*
* If the string is null
, zero
is returned.
*
+ *
+ * NumberUtils.stringToInt(null) = 0
+ * NumberUtils.stringToInt("") = 0
+ * NumberUtils.stringToInt("1") = 1
+ *
+ *
* @param str the string to convert, may be null
* @return the int represented by the string, or zero
if
* conversion fails
+ * @deprecated Use {@link #toInt(String)}
+ * This method will be removed in Commons Lang 3.0
*/
public static int stringToInt(String str) {
- return stringToInt(str, 0);
+ return toInt(str);
}
/**
+ * Convert a String
to an int
, returning
+ * zero
if the conversion fails.
+ *
+ * If the string is null
, zero
is returned.
+ *
+ *
+ * NumberUtils.toInt(null) = 0
+ * NumberUtils.toInt("") = 0
+ * NumberUtils.toInt("1") = 1
+ *
+ *
+ * @param str the string to convert, may be null
+ * @return the int represented by the string, or zero
if
+ * conversion fails
+ * @since 2.1
+ */
+ public static int toInt(String str) {
+ return toInt(str, 0);
+ }
+
+ /**
* Convert a String
to an int
, returning a
* default value if the conversion fails.
*
* If the string is null
, the default value is returned.
*
+ *
+ * NumberUtils.stringToInt(null, 1) = 1
+ * NumberUtils.stringToInt("", 1) = 1
+ * NumberUtils.stringToInt("1", 0) = 1
+ *
+ *
* @param str the string to convert, may be null
* @param defaultValue the default value
* @return the int represented by the string, or the default if conversion fails
+ * @deprecated Use {@link #toInt(String, int)}
+ * This method will be removed in Commons Lang 3.0
*/
public static int stringToInt(String str, int defaultValue) {
+ return toInt(str, defaultValue);
+ }
+
+ /**
+ * Convert a String
to an int
, returning a
+ * default value if the conversion fails.
+ *
+ * If the string is null
, the default value is returned.
+ *
+ *
+ * NumberUtils.toInt(null, 1) = 1
+ * NumberUtils.toInt("", 1) = 1
+ * NumberUtils.toInt("1", 0) = 1
+ *
+ *
+ * @param str the string to convert, may be null
+ * @param defaultValue the default value
+ * @return the int represented by the string, or the default if conversion fails
+ * @since 2.1
+ */
+ public static int toInt(String str, int defaultValue) {
+ if(str == null) {
+ return defaultValue;
+ }
try {
return Integer.parseInt(str);
} catch (NumberFormatException nfe) {
return defaultValue;
}
}
+ /**
+ * Convert a String
to a long
, returning
+ * zero
if the conversion fails.
+ *
+ * If the string is null
, zero
is returned.
+ *
+ *
+ * NumberUtils.toLong(null) = 0L
+ * NumberUtils.toLong("") = 0L
+ * NumberUtils.toLong("1") = 1L
+ *
+ *
+ * @param str the string to convert, may be null
+ * @return the long represented by the string, or 0
if
+ * conversion fails
+ * @since 2.1
+ */
+ public static long toLong(String str) {
+ return toLong(str, 0L);
+ }
+
+ /**
+ * Convert a String
to a long
, returning a
+ * default value if the conversion fails.
+ *
+ * If the string is null
, the default value is returned.
+ *
+ *
+ * NumberUtils.toLong(null, 1L) = 1L
+ * NumberUtils.toLong("", 1L) = 1L
+ * NumberUtils.toLong("1", 0L) = 1L
+ *
+ *
+ * @param str the string to convert, may be null
+ * @param defaultValue the default value
+ * @return the long represented by the string, or the default if conversion fails
+ * @since 2.1
+ */
+ public static long toLong(String str, long defaultValue) {
+ if (str == null) {
+ return defaultValue;
+ }
+ try {
+ return Long.parseLong(str);
+ } catch (NumberFormatException nfe) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Convert a String
to a float
, returning
+ * 0.0f
if the conversion fails.
+ *
+ * If the string str
is null
,
+ * 0.0f
is returned.
+ *
+ *
+ * NumberUtils.toFloat(null) = 0.0f
+ * NumberUtils.toFloat("") = 0.0f
+ * NumberUtils.toFloat("1.5") = 1.5f
+ *
+ *
+ * @param str the string to convert, may be null
+ * @return the float represented by the string, or 0.0f
+ * if conversion fails
+ * @since 2.1
+ */
+ public static float toFloat(String str) {
+ return toFloat(str, 0.0f);
+ }
+
+ /**
+ * Convert a String
to a float
, returning a
+ * default value if the conversion fails.
+ *
+ * If the string str
is null
, the default
+ * value is returned.
+ *
+ *
+ * NumberUtils.toFloat(null, 1.1f) = 1.0f
+ * NumberUtils.toFloat("", 1.1f) = 1.1f
+ * NumberUtils.toFloat("1.5", 0.0f) = 1.5f
+ *
+ *
+ * @param str the string to convert, may be null
+ * @param defaultValue the default value
+ * @return the float represented by the string, or defaultValue
+ * if conversion fails
+ * @since 2.1
+ */
+ public static float toFloat(String str, float defaultValue) {
+ if (str == null) {
+ return defaultValue;
+ }
+ try {
+ return Float.parseFloat(str);
+ } catch (NumberFormatException nfe) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Convert a String
to a double
, returning
+ * 0.0d
if the conversion fails.
+ *
+ * If the string str
is null
,
+ * 0.0d
is returned.
+ *
+ *
+ * NumberUtils.toDouble(null) = 0.0d
+ * NumberUtils.toDouble("") = 0.0d
+ * NumberUtils.toDouble("1.5") = 1.5d
+ *
+ *
+ * @param str the string to convert, may be null
+ * @return the double represented by the string, or 0.0d
+ * if conversion fails
+ * @since 2.1
+ */
+ public static double toDouble(String str) {
+ return toDouble(str, 0.0d);
+ }
+
+ /**
+ * Convert a String
to a double
, returning a
+ * default value if the conversion fails.
+ *
+ * If the string str
is null
, the default
+ * value is returned.
+ *
+ *
+ * NumberUtils.toDouble(null, 1.1d) = 1.1d
+ * NumberUtils.toDouble("", 1.1d) = 1.1d
+ * NumberUtils.toDouble("1.5", 0.0d) = 1.5d
+ *
+ *
+ * @param str the string to convert, may be null
+ * @param defaultValue the default value
+ * @return the double represented by the string, or defaultValue
+ * if conversion fails
+ * @since 2.1
+ */
+ public static double toDouble(String str, double defaultValue) {
+ if (str == null) {
+ return defaultValue;
+ }
+ try {
+ return Double.parseDouble(str);
+ } catch (NumberFormatException nfe) {
+ return defaultValue;
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Convert a String
to a byte
, returning
+ * zero
if the conversion fails.
+ *
+ * If the string is null
, zero
is returned.
+ *
+ *
+ * NumberUtils.toByte(null) = 0
+ * NumberUtils.toByte("") = 0
+ * NumberUtils.toByte("1") = 1
+ *
+ *
+ * @param str the string to convert, may be null
+ * @return the byte represented by the string, or zero
if
+ * conversion fails
+ * @since 2.5
+ */
+ public static byte toByte(String str) {
+ return toByte(str, (byte) 0);
+ }
+
+ /**
+ * Convert a String
to a byte
, returning a
+ * default value if the conversion fails.
+ *
+ * If the string is null
, the default value is returned.
+ *
+ *
+ * NumberUtils.toByte(null, 1) = 1
+ * NumberUtils.toByte("", 1) = 1
+ * NumberUtils.toByte("1", 0) = 1
+ *
+ *
+ * @param str the string to convert, may be null
+ * @param defaultValue the default value
+ * @return the byte represented by the string, or the default if conversion fails
+ * @since 2.5
+ */
+ public static byte toByte(String str, byte defaultValue) {
+ if(str == null) {
+ return defaultValue;
+ }
+ try {
+ return Byte.parseByte(str);
+ } catch (NumberFormatException nfe) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Convert a String
to a short
, returning
+ * zero
if the conversion fails.
+ *
+ * If the string is null
, zero
is returned.
+ *
+ *
+ * NumberUtils.toShort(null) = 0
+ * NumberUtils.toShort("") = 0
+ * NumberUtils.toShort("1") = 1
+ *
+ *
+ * @param str the string to convert, may be null
+ * @return the short represented by the string, or zero
if
+ * conversion fails
+ * @since 2.5
+ */
+ public static short toShort(String str) {
+ return toShort(str, (short) 0);
+ }
+
+ /**
+ * Convert a String
to an short
, returning a
+ * default value if the conversion fails.
+ *
+ * If the string is null
, the default value is returned.
+ *
+ *
+ * NumberUtils.toShort(null, 1) = 1
+ * NumberUtils.toShort("", 1) = 1
+ * NumberUtils.toShort("1", 0) = 1
+ *
+ *
+ * @param str the string to convert, may be null
+ * @param defaultValue the default value
+ * @return the short represented by the string, or the default if conversion fails
+ * @since 2.5
+ */
+ public static short toShort(String str, short defaultValue) {
+ if(str == null) {
+ return defaultValue;
+ }
+ try {
+ return Short.parseShort(str);
+ } catch (NumberFormatException nfe) {
+ return defaultValue;
+ }
+ }
+
//-----------------------------------------------------------------------
// must handle Long, Float, Integer, Float, Short,
// BigDecimal, BigInteger and Byte
@@ -243,7 +520,7 @@
if (decPos > -1) {
if (expPos > -1) {
- if (expPos < decPos) {
+ if (expPos < decPos || expPos > str.length()) {
throw new NumberFormatException(str + " is not a valid number.");
}
dec = str.substring(decPos + 1, expPos);
@@ -253,13 +530,16 @@
mant = str.substring(0, decPos);
} else {
if (expPos > -1) {
+ if (expPos > str.length()) {
+ throw new NumberFormatException(str + " is not a valid number.");
+ }
mant = str.substring(0, expPos);
} else {
mant = str;
}
dec = null;
}
- if (!Character.isDigit(lastChar)) {
+ if (!Character.isDigit(lastChar) && lastChar != '.') {
if (expPos > -1 && expPos < str.length() - 1) {
exp = str.substring(expPos + 1, str.length() - 1);
} else {
@@ -273,8 +553,7 @@
case 'L' :
if (dec == null
&& exp == null
- && isDigits(numeric.substring(1))
- && (numeric.charAt(0) == '-' || Character.isDigit(numeric.charAt(0)))) {
+ && (numeric.charAt(0) == '-' && isDigits(numeric.substring(1)) || isDigits(numeric))) {
try {
return createLong(numeric);
} catch (NumberFormatException nfe) {
@@ -290,13 +569,14 @@
Float f = NumberUtils.createFloat(numeric);
if (!(f.isInfinite() || (f.floatValue() == 0.0F && !allZeros))) {
//If it's too big for a float or the float value = 0 and the string
- //has non-zeros in it, then float doens't have the presision we want
+ //has non-zeros in it, then float does not have the precision we want
return f;
}
} catch (NumberFormatException nfe) {
+ // ignore the bad number
}
- //Fall through
+ //$FALL-THROUGH$
case 'd' :
case 'D' :
try {
@@ -305,12 +585,14 @@
return d;
}
} catch (NumberFormatException nfe) {
+ // ignore the bad number
}
try {
return createBigDecimal(numeric);
} catch (NumberFormatException e) {
+ // ignore the bad number
}
- //Fall through
+ //$FALL-THROUGH$
default :
throw new NumberFormatException(str + " is not a valid number.");
@@ -328,10 +610,12 @@
try {
return createInteger(str);
} catch (NumberFormatException nfe) {
+ // ignore the bad number
}
try {
return createLong(str);
} catch (NumberFormatException nfe) {
+ // ignore the bad number
}
return createBigInteger(str);
@@ -344,13 +628,15 @@
return f;
}
} catch (NumberFormatException nfe) {
+ // ignore the bad number
}
try {
Double d = createDouble(str);
if (!(d.isInfinite() || (d.doubleValue() == 0.0D && !allZeros))) {
return d;
}
} catch (NumberFormatException nfe) {
+ // ignore the bad number
}
return createBigDecimal(str);
@@ -565,13 +851,41 @@
return min;
}
+ /**
+ * Returns the minimum value in an array.
+ *
+ * @param array an array, must not be null or empty
+ * @return the minimum value in the array
+ * @throws IllegalArgumentException if array
is null
+ * @throws IllegalArgumentException if array
is empty
+ */
+ public static byte min(byte[] array) {
+ // Validates input
+ if (array == null) {
+ throw new IllegalArgumentException("The Array must not be null");
+ } else if (array.length == 0) {
+ throw new IllegalArgumentException("Array cannot be empty.");
+ }
+
+ // Finds and returns min
+ byte min = array[0];
+ for (int i = 1; i < array.length; i++) {
+ if (array[i] < min) {
+ min = array[i];
+ }
+ }
+
+ return min;
+ }
+
/**
* Returns the minimum value in an array.
*
* @param array an array, must not be null or empty
* @return the minimum value in the array
* @throws IllegalArgumentException if array
is null
* @throws IllegalArgumentException if array
is empty
+ * @see IEEE754rUtils#min(double[]) IEEE754rUtils for a version of this method that handles NaN differently
*/
public static double min(double[] array) {
// Validates input
@@ -584,6 +898,9 @@
// Finds and returns min
double min = array[0];
for (int i = 1; i < array.length; i++) {
+ if (Double.isNaN(array[i])) {
+ return Double.NaN;
+ }
if (array[i] < min) {
min = array[i];
}
@@ -599,6 +916,7 @@
* @return the minimum value in the array
* @throws IllegalArgumentException if array
is null
* @throws IllegalArgumentException if array
is empty
+ * @see IEEE754rUtils#min(float[]) IEEE754rUtils for a version of this method that handles NaN differently
*/
public static float min(float[] array) {
// Validates input
@@ -611,6 +929,9 @@
// Finds and returns min
float min = array[0];
for (int i = 1; i < array.length; i++) {
+ if (Float.isNaN(array[i])) {
+ return Float.NaN;
+ }
if (array[i] < min) {
min = array[i];
}
@@ -710,6 +1031,34 @@
* @throws IllegalArgumentException if array
is null
* @throws IllegalArgumentException if array
is empty
*/
+ public static byte max(byte[] array) {
+ // Validates input
+ if (array == null) {
+ throw new IllegalArgumentException("The Array must not be null");
+ } else if (array.length == 0) {
+ throw new IllegalArgumentException("Array cannot be empty.");
+ }
+
+ // Finds and returns max
+ byte max = array[0];
+ for (int i = 1; i < array.length; i++) {
+ if (array[i] > max) {
+ max = array[i];
+ }
+ }
+
+ return max;
+ }
+
+ /**
+ * Returns the maximum value in an array.
+ *
+ * @param array an array, must not be null or empty
+ * @return the minimum value in the array
+ * @throws IllegalArgumentException if array
is null
+ * @throws IllegalArgumentException if array
is empty
+ * @see IEEE754rUtils#max(double[]) IEEE754rUtils for a version of this method that handles NaN differently
+ */
public static double max(double[] array) {
// Validates input
if (array== null) {
@@ -721,6 +1070,9 @@
// Finds and returns max
double max = array[0];
for (int j = 1; j < array.length; j++) {
+ if (Double.isNaN(array[j])) {
+ return Double.NaN;
+ }
if (array[j] > max) {
max = array[j];
}
@@ -736,6 +1088,7 @@
* @return the minimum value in the array
* @throws IllegalArgumentException if array
is null
* @throws IllegalArgumentException if array
is empty
+ * @see IEEE754rUtils#max(float[]) IEEE754rUtils for a version of this method that handles NaN differently
*/
public static float max(float[] array) {
// Validates input
@@ -748,6 +1101,9 @@
// Finds and returns max
float max = array[0];
for (int j = 1; j < array.length; j++) {
+ if (Float.isNaN(array[j])) {
+ return Float.NaN;
+ }
if (array[j] > max) {
max = array[j];
}
@@ -840,6 +1196,7 @@
* @param b value 2
* @param c value 3
* @return the smallest of the values
+ * @see IEEE754rUtils#min(double, double, double) for a version of this method that handles NaN differently
*/
public static double min(double a, double b, double c) {
return Math.min(Math.min(a, b), c);
@@ -855,6 +1212,7 @@
* @param b value 2
* @param c value 3
* @return the smallest of the values
+ * @see IEEE754rUtils#min(float, float, float) for a version of this method that handles NaN differently
*/
public static float min(float a, float b, float c) {
return Math.min(Math.min(a, b), c);
@@ -944,6 +1302,7 @@
* @param b value 2
* @param c value 3
* @return the largest of the values
+ * @see IEEE754rUtils#max(double, double, double) for a version of this method that handles NaN differently
*/
public static double max(double a, double b, double c) {
return Math.max(Math.max(a, b), c);
@@ -959,6 +1318,7 @@
* @param b value 2
* @param c value 3
* @return the largest of the values
+ * @see IEEE754rUtils#max(float, float, float) for a version of this method that handles NaN differently
*/
public static float max(float a, float b, float c) {
return Math.max(Math.max(a, b), c);
@@ -982,7 +1342,7 @@
* NaN
* Positive infinity
* Maximum double
- * Normal positve numbers
+ * Normal positive numbers
* +0.0
* -0.0
* Normal negative numbers
@@ -1031,7 +1391,7 @@
/**
* Compares two floats for order.
*
- * This method is more comprhensive than the standard Java greater than,
+ *
This method is more comprehensive than the standard Java greater than,
* less than and equals operators.
*
* - It returns
-1
if the first value is less than the second.
@@ -1044,7 +1404,7 @@
* - NaN
*
- Positive infinity
*
- Maximum float
- *
- Normal positve numbers
+ *
- Normal positive numbers
*
- +0.0
*
- -0.0
*
- Normal negative numbers
@@ -1101,7 +1461,7 @@
* @return
true
if str contains only unicode numeric
*/
public static boolean isDigits(String str) {
- if ((str == null) || (str.length() == 0)) {
+ if (StringUtils.isEmpty(str)) {
return false;
}
for (int i = 0; i < str.length(); i++) {
@@ -1126,7 +1486,7 @@
* @return true
if the string is a correctly formatted number
*/
public static boolean isNumber(String str) {
- if ((str == null) || (str.length() == 0)) {
+ if (StringUtils.isEmpty(str)) {
return false;
}
char[] chars = str.toCharArray();
@@ -1201,6 +1561,14 @@
// can't have an E at the last byte
return false;
}
+ if (chars[i] == '.') {
+ if (hasDecPoint || hasExp) {
+ // two decimal points or dec in exponent
+ return false;
+ }
+ // single trailing decimal point after non-exponent is ok
+ return foundDigit;
+ }
if (!allowSigns
&& (chars[i] == 'd'
|| chars[i] == 'D'
@@ -1210,7 +1578,7 @@
}
if (chars[i] == 'l'
|| chars[i] == 'L') {
- // not allowing L with an exponoent
+ // not allowing L with an exponent
return foundDigit && !hasExp;
}
// last character is illegal
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/math/RandomUtils.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/math/RandomUtils.java (.../RandomUtils.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/math/RandomUtils.java (.../RandomUtils.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,55 +1,20 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
*
- * Copyright (c) 2002 The Apache Software Foundation. All rights
- * reserved.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+ * 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.
*/
package org.apache.commons.lang.math;
@@ -60,12 +25,15 @@
* {@link java.util.Random} methods via the {@link java.lang.Math#random()}
* method and its system-wide Random
object.
*
- * @author Henri Yandell
+ * @author Gary D. Gregory
* @since 2.0
* @version $Id$
*/
public class RandomUtils {
+ /**
+ * An instance of {@link JVMRandom}.
+ */
public static final Random JVM_RANDOM = new JVMRandom();
// should be possible for JVM_RANDOM?
@@ -76,43 +44,71 @@
/**
* Returns the next pseudorandom, uniformly distributed int value
* from the Math.random() sequence.
- *
+ * N.B. All values are >= 0.
* @return the random int
*/
public static int nextInt() {
return nextInt(JVM_RANDOM);
}
- public static int nextInt(Random rnd) {
- return rnd.nextInt();
+
+ /**
+ * Returns the next pseudorandom, uniformly distributed int value
+ * from the given random
sequence.
+ *
+ * @param random the Random sequence generator.
+ * @return the random int
+ */
+ public static int nextInt(Random random) {
+ return random.nextInt();
}
+
/**
* Returns a pseudorandom, uniformly distributed int value
* between 0
(inclusive) and the specified value
* (exclusive), from the Math.random() sequence.
*
* @param n the specified exclusive max-value
- *
* @return the random int
*/
public static int nextInt(int n) {
return nextInt(JVM_RANDOM, n);
}
- public static int nextInt(Random rnd, int n) {
+
+ /**
+ * Returns a pseudorandom, uniformly distributed int value
+ * between 0
(inclusive) and the specified value
+ * (exclusive), from the given Random sequence.
+ *
+ * @param random the Random sequence generator.
+ * @param n the specified exclusive max-value
+ * @return the random int
+ */
+ public static int nextInt(Random random, int n) {
// check this cannot return 'n'
- return rnd.nextInt(n);
+ return random.nextInt(n);
}
+
/**
* Returns the next pseudorandom, uniformly distributed long value
* from the Math.random() sequence.
- *
+ * N.B. All values are >= 0.
* @return the random long
*/
public static long nextLong() {
return nextLong(JVM_RANDOM);
}
- public static long nextLong(Random rnd) {
- return rnd.nextLong();
+
+ /**
+ * Returns the next pseudorandom, uniformly distributed long value
+ * from the given Random sequence.
+ *
+ * @param random the Random sequence generator.
+ * @return the random long
+ */
+ public static long nextLong(Random random) {
+ return random.nextLong();
}
+
/**
* Returns the next pseudorandom, uniformly distributed boolean value
* from the Math.random() sequence.
@@ -122,9 +118,18 @@
public static boolean nextBoolean() {
return nextBoolean(JVM_RANDOM);
}
- public static boolean nextBoolean(Random rnd) {
- return rnd.nextBoolean();
+
+ /**
+ * Returns the next pseudorandom, uniformly distributed boolean value
+ * from the given random sequence.
+ *
+ * @param random the Random sequence generator.
+ * @return the random boolean
+ */
+ public static boolean nextBoolean(Random random) {
+ return random.nextBoolean();
}
+
/**
* Returns the next pseudorandom, uniformly distributed float value
* between 0.0
and 1.0
from the Math.random()
@@ -135,19 +140,40 @@
public static float nextFloat() {
return nextFloat(JVM_RANDOM);
}
- public static float nextFloat(Random rnd) {
- return rnd.nextFloat();
+
+ /**
+ *
Returns the next pseudorandom, uniformly distributed float value
+ * between 0.0
and 1.0
from the given Random
+ * sequence.
+ *
+ * @param random the Random sequence generator.
+ * @return the random float
+ */
+ public static float nextFloat(Random random) {
+ return random.nextFloat();
}
+
/**
- * Synonymous to the Math.random() call.
+ * Returns the next pseudorandom, uniformly distributed float value
+ * between 0.0
and 1.0
from the Math.random()
+ * sequence.
*
* @return the random double
*/
public static double nextDouble() {
return nextDouble(JVM_RANDOM);
}
- public static double nextDouble(Random rnd) {
- return rnd.nextDouble();
+
+ /**
+ * Returns the next pseudorandom, uniformly distributed float value
+ * between 0.0
and 1.0
from the given Random
+ * sequence.
+ *
+ * @param random the Random sequence generator.
+ * @return the random double
+ */
+ public static double nextDouble(Random random) {
+ return random.nextDouble();
}
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/math/Range.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/math/Range.java (.../Range.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/math/Range.java (.../Range.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,66 +1,31 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang.math;
+import org.apache.commons.lang.text.StrBuilder;
+
/**
* Range
represents a range of numbers of the same type.
*
* Specific subclasses hold the range values as different types. Each
* subclass should be immutable and {@link java.io.Serializable Serializable}
* if possible.
*
- * @author Stephen Colebourne
+ * @author Apache Software Foundation
* @since 2.0
* @version $Id$
*/
@@ -236,7 +201,7 @@
* range by long
comparison
*/
public boolean containsLong(long value) {
- return (value >= getMinimumLong() && value <= getMaximumLong());
+ return value >= getMinimumLong() && value <= getMaximumLong();
}
/**
@@ -270,7 +235,7 @@
* range by int
comparison
*/
public boolean containsInteger(int value) {
- return (value >= getMinimumInteger() && value <= getMaximumInteger());
+ return value >= getMinimumInteger() && value <= getMaximumInteger();
}
/**
@@ -306,7 +271,7 @@
public boolean containsDouble(double value) {
int compareMin = NumberUtils.compare(getMinimumDouble(), value);
int compareMax = NumberUtils.compare(getMaximumDouble(), value);
- return (compareMin <= 0 && compareMax >= 0);
+ return compareMin <= 0 && compareMax >= 0;
}
/**
@@ -342,7 +307,7 @@
public boolean containsFloat(float value) {
int compareMin = NumberUtils.compare(getMinimumFloat(), value);
int compareMax = NumberUtils.compare(getMaximumFloat(), value);
- return (compareMin <= 0 && compareMax >= 0);
+ return compareMin <= 0 && compareMax >= 0;
}
// Range tests
@@ -456,7 +421,7 @@
* @return the String
representation of this range
*/
public String toString() {
- StringBuffer buf = new StringBuffer(32);
+ StrBuilder buf = new StrBuilder(32);
buf.append("Range[");
buf.append(getMinimumNumber());
buf.append(',');
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/math/package.html
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/math/package.html (.../package.html) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/math/package.html (.../package.html) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,7 +1,25 @@
+
-Extends java.math
for business mathematical classes. This package is intended for business
-mathematical classes, not scientific ones.
+Extends {@link java.math} for business mathematical classes. This package is intended for business
+mathematical use, not scientific use. See Commons Math
+for a more complete set of mathematical classes.
@since 2.0
+These classes are immutable, and therefore thread-safe.
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/Mutable.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/Mutable.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/Mutable.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.commons.lang.mutable;
+
+/**
+ * Provides mutable access to a value.
+ *
+ * Mutable
is used as a generic interface to the implementations in this package.
+ *
+ * A typical use case would be to enable a primitive or string to be passed to a method and allow that method to
+ * effectively change the value of the primitive/string. Another use case is to store a frequently changing primitive in
+ * a collection (for example a total in a map) without needing to create new Integer/Long wrapper objects.
+ *
+ * @author Apache Software Foundation
+ * @author Matthew Hawthorne
+ * @since 2.1
+ * @version $Id$
+ */
+public interface Mutable {
+
+ /**
+ * Gets the value of this mutable.
+ *
+ * @return the stored value
+ */
+ Object getValue();
+
+ /**
+ * Sets the value of this mutable.
+ *
+ * @param value
+ * the value to store
+ * @throws NullPointerException
+ * if the object is null and null is invalid
+ * @throws ClassCastException
+ * if the type is invalid
+ */
+ void setValue(Object value);
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/MutableBoolean.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/MutableBoolean.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/MutableBoolean.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,192 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.commons.lang.mutable;
+
+import java.io.Serializable;
+
+import org.apache.commons.lang.BooleanUtils;
+
+/**
+ * A mutable boolean
wrapper.
+ *
+ * @see Boolean
+ * @since 2.2
+ * @author Apache Software Foundation
+ * @version $Id$
+ */
+public class MutableBoolean implements Mutable, Serializable, Comparable {
+
+ /**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = -4830728138360036487L;
+
+ /** The mutable value. */
+ private boolean value;
+
+ /**
+ * Constructs a new MutableBoolean with the default value of false.
+ */
+ public MutableBoolean() {
+ super();
+ }
+
+ /**
+ * Constructs a new MutableBoolean with the specified value.
+ *
+ * @param value the initial value to store
+ */
+ public MutableBoolean(boolean value) {
+ super();
+ this.value = value;
+ }
+
+ /**
+ * Constructs a new MutableBoolean with the specified value.
+ *
+ * @param value the initial value to store, not null
+ * @throws NullPointerException if the object is null
+ */
+ public MutableBoolean(Boolean value) {
+ super();
+ this.value = value.booleanValue();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the value as a Boolean instance.
+ *
+ * @return the value as a Boolean, never null
+ */
+ public Object getValue() {
+ return BooleanUtils.toBooleanObject(this.value);
+ }
+
+ /**
+ * Sets the value.
+ *
+ * @param value the value to set
+ */
+ public void setValue(boolean value) {
+ this.value = value;
+ }
+
+ /**
+ * Sets the value from any Boolean instance.
+ *
+ * @param value the value to set, not null
+ * @throws NullPointerException if the object is null
+ */
+ public void setValue(Object value) {
+ setValue(((Boolean) value).booleanValue());
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Checks if the current value is true
.
+ *
+ * @return true
if the current value is true
+ * @since 2.5
+ */
+ public boolean isTrue() {
+ return value == true;
+ }
+
+ /**
+ * Checks if the current value is false
.
+ *
+ * @return true
if the current value is false
+ * @since 2.5
+ */
+ public boolean isFalse() {
+ return value == false;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Returns the value of this MutableBoolean as a boolean.
+ *
+ * @return the boolean value represented by this object.
+ */
+ public boolean booleanValue() {
+ return value;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets this mutable as an instance of Boolean.
+ *
+ * @return a Boolean instance containing the value from this mutable, never null
+ * @since 2.5
+ */
+ public Boolean toBoolean() {
+ return BooleanUtils.toBooleanObject(this.value);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Compares this object to the specified object. The result is true
if and only if the argument is
+ * not null
and is an MutableBoolean
object that contains the same
+ * boolean
value as this object.
+ *
+ * @param obj the object to compare with, null returns false
+ * @return true
if the objects are the same; false
otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (obj instanceof MutableBoolean) {
+ return value == ((MutableBoolean) obj).booleanValue();
+ }
+ return false;
+ }
+
+ /**
+ * Returns a suitable hash code for this mutable.
+ *
+ * @return the hash code returned by Boolean.TRUE
or Boolean.FALSE
+ */
+ public int hashCode() {
+ return value ? Boolean.TRUE.hashCode() : Boolean.FALSE.hashCode();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Compares this mutable to another in ascending order.
+ *
+ * @param obj the other mutable to compare to, not null
+ * @return negative if this is less, zero if equal, positive if greater
+ * where false is less than true
+ */
+ public int compareTo(Object obj) {
+ MutableBoolean other = (MutableBoolean) obj;
+ boolean anotherVal = other.value;
+ return value == anotherVal ? 0 : (value ? 1 : -1);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Returns the String value of this mutable.
+ *
+ * @return the mutable value as a string
+ */
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/MutableByte.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/MutableByte.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/MutableByte.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,277 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang.mutable;
+
+/**
+ * A mutable byte
wrapper.
+ *
+ * @see Byte
+ * @since 2.1
+ * @author Apache Software Foundation
+ * @version $Id$
+ */
+public class MutableByte extends Number implements Comparable, Mutable {
+
+ /**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = -1585823265L;
+
+ /** The mutable value. */
+ private byte value;
+
+ /**
+ * Constructs a new MutableByte with the default value of zero.
+ */
+ public MutableByte() {
+ super();
+ }
+
+ /**
+ * Constructs a new MutableByte with the specified value.
+ *
+ * @param value the initial value to store
+ */
+ public MutableByte(byte value) {
+ super();
+ this.value = value;
+ }
+
+ /**
+ * Constructs a new MutableByte with the specified value.
+ *
+ * @param value the initial value to store, not null
+ * @throws NullPointerException if the object is null
+ */
+ public MutableByte(Number value) {
+ super();
+ this.value = value.byteValue();
+ }
+
+ /**
+ * Constructs a new MutableByte parsing the given string.
+ *
+ * @param value the string to parse, not null
+ * @throws NumberFormatException if the string cannot be parsed into a byte
+ * @since 2.5
+ */
+ public MutableByte(String value) throws NumberFormatException {
+ super();
+ this.value = Byte.parseByte(value);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the value as a Byte instance.
+ *
+ * @return the value as a Byte, never null
+ */
+ public Object getValue() {
+ return new Byte(this.value);
+ }
+
+ /**
+ * Sets the value.
+ *
+ * @param value the value to set
+ */
+ public void setValue(byte value) {
+ this.value = value;
+ }
+
+ /**
+ * Sets the value from any Number instance.
+ *
+ * @param value the value to set, not null
+ * @throws NullPointerException if the object is null
+ * @throws ClassCastException if the type is not a {@link Number}
+ */
+ public void setValue(Object value) {
+ setValue(((Number) value).byteValue());
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Increments the value.
+ *
+ * @since Commons Lang 2.2
+ */
+ public void increment() {
+ value++;
+ }
+
+ /**
+ * Decrements the value.
+ *
+ * @since Commons Lang 2.2
+ */
+ public void decrement() {
+ value--;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Adds a value to the value of this instance.
+ *
+ * @param operand the value to add, not null
+ * @since Commons Lang 2.2
+ */
+ public void add(byte operand) {
+ this.value += operand;
+ }
+
+ /**
+ * Adds a value to the value of this instance.
+ *
+ * @param operand the value to add, not null
+ * @throws NullPointerException if the object is null
+ * @since Commons Lang 2.2
+ */
+ public void add(Number operand) {
+ this.value += operand.byteValue();
+ }
+
+ /**
+ * Subtracts a value from the value of this instance.
+ *
+ * @param operand the value to subtract, not null
+ * @since Commons Lang 2.2
+ */
+ public void subtract(byte operand) {
+ this.value -= operand;
+ }
+
+ /**
+ * Subtracts a value from the value of this instance.
+ *
+ * @param operand the value to subtract, not null
+ * @throws NullPointerException if the object is null
+ * @since Commons Lang 2.2
+ */
+ public void subtract(Number operand) {
+ this.value -= operand.byteValue();
+ }
+
+ //-----------------------------------------------------------------------
+ // shortValue relies on Number implementation
+ /**
+ * Returns the value of this MutableByte as a byte.
+ *
+ * @return the numeric value represented by this object after conversion to type byte.
+ */
+ public byte byteValue() {
+ return value;
+ }
+
+ /**
+ * Returns the value of this MutableByte as an int.
+ *
+ * @return the numeric value represented by this object after conversion to type int.
+ */
+ public int intValue() {
+ return value;
+ }
+
+ /**
+ * Returns the value of this MutableByte as a long.
+ *
+ * @return the numeric value represented by this object after conversion to type long.
+ */
+ public long longValue() {
+ return value;
+ }
+
+ /**
+ * Returns the value of this MutableByte as a float.
+ *
+ * @return the numeric value represented by this object after conversion to type float.
+ */
+ public float floatValue() {
+ return value;
+ }
+
+ /**
+ * Returns the value of this MutableByte as a double.
+ *
+ * @return the numeric value represented by this object after conversion to type double.
+ */
+ public double doubleValue() {
+ return value;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets this mutable as an instance of Byte.
+ *
+ * @return a Byte instance containing the value from this mutable
+ */
+ public Byte toByte() {
+ return new Byte(byteValue());
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Compares this object to the specified object. The result is true
if and only if the argument is
+ * not null
and is a MutableByte
object that contains the same byte
value
+ * as this object.
+ *
+ * @param obj the object to compare with, null returns false
+ * @return true
if the objects are the same; false
otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (obj instanceof MutableByte) {
+ return value == ((MutableByte) obj).byteValue();
+ }
+ return false;
+ }
+
+ /**
+ * Returns a suitable hash code for this mutable.
+ *
+ * @return a suitable hash code
+ */
+ public int hashCode() {
+ return value;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Compares this mutable to another in ascending order.
+ *
+ * @param obj the other mutable to compare to, not null
+ * @return negative if this is less, zero if equal, positive if greater
+ * @throws ClassCastException if the argument is not a MutableByte
+ */
+ public int compareTo(Object obj) {
+ MutableByte other = (MutableByte) obj;
+ byte anotherVal = other.value;
+ return value < anotherVal ? -1 : (value == anotherVal ? 0 : 1);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Returns the String value of this mutable.
+ *
+ * @return the mutable value as a string
+ */
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/MutableDouble.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/MutableDouble.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/MutableDouble.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,309 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang.mutable;
+
+import org.apache.commons.lang.math.NumberUtils;
+
+/**
+ * A mutable double
wrapper.
+ *
+ * @see Double
+ * @since 2.1
+ * @author Apache Software Foundation
+ * @version $Id$
+ */
+public class MutableDouble extends Number implements Comparable, Mutable {
+
+ /**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = 1587163916L;
+
+ /** The mutable value. */
+ private double value;
+
+ /**
+ * Constructs a new MutableDouble with the default value of zero.
+ */
+ public MutableDouble() {
+ super();
+ }
+
+ /**
+ * Constructs a new MutableDouble with the specified value.
+ *
+ * @param value the initial value to store
+ */
+ public MutableDouble(double value) {
+ super();
+ this.value = value;
+ }
+
+ /**
+ * Constructs a new MutableDouble with the specified value.
+ *
+ * @param value the initial value to store, not null
+ * @throws NullPointerException if the object is null
+ */
+ public MutableDouble(Number value) {
+ super();
+ this.value = value.doubleValue();
+ }
+
+ /**
+ * Constructs a new MutableDouble parsing the given string.
+ *
+ * @param value the string to parse, not null
+ * @throws NumberFormatException if the string cannot be parsed into a double
+ * @since 2.5
+ */
+ public MutableDouble(String value) throws NumberFormatException {
+ super();
+ this.value = Double.parseDouble(value);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the value as a Double instance.
+ *
+ * @return the value as a Double, never null
+ */
+ public Object getValue() {
+ return new Double(this.value);
+ }
+
+ /**
+ * Sets the value.
+ *
+ * @param value the value to set
+ */
+ public void setValue(double value) {
+ this.value = value;
+ }
+
+ /**
+ * Sets the value from any Number instance.
+ *
+ * @param value the value to set, not null
+ * @throws NullPointerException if the object is null
+ * @throws ClassCastException if the type is not a {@link Number}
+ */
+ public void setValue(Object value) {
+ setValue(((Number) value).doubleValue());
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Checks whether the double value is the special NaN value.
+ *
+ * @return true if NaN
+ */
+ public boolean isNaN() {
+ return Double.isNaN(value);
+ }
+
+ /**
+ * Checks whether the double value is infinite.
+ *
+ * @return true if infinite
+ */
+ public boolean isInfinite() {
+ return Double.isInfinite(value);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Increments the value.
+ *
+ * @since Commons Lang 2.2
+ */
+ public void increment() {
+ value++;
+ }
+
+ /**
+ * Decrements the value.
+ *
+ * @since Commons Lang 2.2
+ */
+ public void decrement() {
+ value--;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Adds a value to the value of this instance.
+ *
+ * @param operand the value to add
+ * @since Commons Lang 2.2
+ */
+ public void add(double operand) {
+ this.value += operand;
+ }
+
+ /**
+ * Adds a value to the value of this instance.
+ *
+ * @param operand the value to add, not null
+ * @throws NullPointerException if the object is null
+ * @since Commons Lang 2.2
+ */
+ public void add(Number operand) {
+ this.value += operand.doubleValue();
+ }
+
+ /**
+ * Subtracts a value from the value of this instance.
+ *
+ * @param operand the value to subtract, not null
+ * @since Commons Lang 2.2
+ */
+ public void subtract(double operand) {
+ this.value -= operand;
+ }
+
+ /**
+ * Subtracts a value from the value of this instance.
+ *
+ * @param operand the value to subtract, not null
+ * @throws NullPointerException if the object is null
+ * @since Commons Lang 2.2
+ */
+ public void subtract(Number operand) {
+ this.value -= operand.doubleValue();
+ }
+
+ //-----------------------------------------------------------------------
+ // shortValue and bytValue rely on Number implementation
+ /**
+ * Returns the value of this MutableDouble as an int.
+ *
+ * @return the numeric value represented by this object after conversion to type int.
+ */
+ public int intValue() {
+ return (int) value;
+ }
+
+ /**
+ * Returns the value of this MutableDouble as a long.
+ *
+ * @return the numeric value represented by this object after conversion to type long.
+ */
+ public long longValue() {
+ return (long) value;
+ }
+
+ /**
+ * Returns the value of this MutableDouble as a float.
+ *
+ * @return the numeric value represented by this object after conversion to type float.
+ */
+ public float floatValue() {
+ return (float) value;
+ }
+
+ /**
+ * Returns the value of this MutableDouble as a double.
+ *
+ * @return the numeric value represented by this object after conversion to type double.
+ */
+ public double doubleValue() {
+ return value;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets this mutable as an instance of Double.
+ *
+ * @return a Double instance containing the value from this mutable, never null
+ */
+ public Double toDouble() {
+ return new Double(doubleValue());
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Compares this object against the specified object. The result is true
if and only if the argument
+ * is not null
and is a Double
object that represents a double that has the identical
+ * bit pattern to the bit pattern of the double represented by this object. For this purpose, two
+ * double
values are considered to be the same if and only if the method
+ * {@link Double#doubleToLongBits(double)}returns the same long value when applied to each.
+ *
+ * Note that in most cases, for two instances of class Double
,d1
and d2
,
+ * the value of d1.equals(d2)
is true
if and only if
+ *
+ *
+ * d1.doubleValue() == d2.doubleValue()
+ *
+ *
+ *
+ *
+ * also has the value true
. However, there are two exceptions:
+ *
+ * - If
d1
and d2
both represent Double.NaN
, then the
+ * equals
method returns true
, even though Double.NaN==Double.NaN
has
+ * the value false
.
+ * - If
d1
represents +0.0
while d2
represents -0.0
,
+ * or vice versa, the equal
test has the value false
, even though
+ * +0.0==-0.0
has the value true
. This allows hashtables to operate properly.
+ *
+ *
+ * @param obj the object to compare with, null returns false
+ * @return true
if the objects are the same; false
otherwise.
+ */
+ public boolean equals(Object obj) {
+ return (obj instanceof MutableDouble)
+ && (Double.doubleToLongBits(((MutableDouble) obj).value) == Double.doubleToLongBits(value));
+ }
+
+ /**
+ * Returns a suitable hash code for this mutable.
+ *
+ * @return a suitable hash code
+ */
+ public int hashCode() {
+ long bits = Double.doubleToLongBits(value);
+ return (int) (bits ^ (bits >>> 32));
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Compares this mutable to another in ascending order.
+ *
+ * @param obj the other mutable to compare to, not null
+ * @return negative if this is less, zero if equal, positive if greater
+ * @throws ClassCastException if the argument is not a MutableDouble
+ */
+ public int compareTo(Object obj) {
+ MutableDouble other = (MutableDouble) obj;
+ double anotherVal = other.value;
+ return NumberUtils.compare(value, anotherVal);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Returns the String value of this mutable.
+ *
+ * @return the mutable value as a string
+ */
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/MutableFloat.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/MutableFloat.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/MutableFloat.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,309 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang.mutable;
+
+import org.apache.commons.lang.math.NumberUtils;
+
+/**
+ * A mutable float
wrapper.
+ *
+ * @see Float
+ * @since 2.1
+ * @author Apache Software Foundation
+ * @version $Id$
+ */
+public class MutableFloat extends Number implements Comparable, Mutable {
+
+ /**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = 5787169186L;
+
+ /** The mutable value. */
+ private float value;
+
+ /**
+ * Constructs a new MutableFloat with the default value of zero.
+ */
+ public MutableFloat() {
+ super();
+ }
+
+ /**
+ * Constructs a new MutableFloat with the specified value.
+ *
+ * @param value the initial value to store
+ */
+ public MutableFloat(float value) {
+ super();
+ this.value = value;
+ }
+
+ /**
+ * Constructs a new MutableFloat with the specified value.
+ *
+ * @param value the initial value to store, not null
+ * @throws NullPointerException if the object is null
+ */
+ public MutableFloat(Number value) {
+ super();
+ this.value = value.floatValue();
+ }
+
+ /**
+ * Constructs a new MutableFloat parsing the given string.
+ *
+ * @param value the string to parse, not null
+ * @throws NumberFormatException if the string cannot be parsed into a float
+ * @since 2.5
+ */
+ public MutableFloat(String value) throws NumberFormatException {
+ super();
+ this.value = Float.parseFloat(value);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the value as a Float instance.
+ *
+ * @return the value as a Float, never null
+ */
+ public Object getValue() {
+ return new Float(this.value);
+ }
+
+ /**
+ * Sets the value.
+ *
+ * @param value the value to set
+ */
+ public void setValue(float value) {
+ this.value = value;
+ }
+
+ /**
+ * Sets the value from any Number instance.
+ *
+ * @param value the value to set, not null
+ * @throws NullPointerException if the object is null
+ * @throws ClassCastException if the type is not a {@link Number}
+ */
+ public void setValue(Object value) {
+ setValue(((Number) value).floatValue());
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Checks whether the float value is the special NaN value.
+ *
+ * @return true if NaN
+ */
+ public boolean isNaN() {
+ return Float.isNaN(value);
+ }
+
+ /**
+ * Checks whether the float value is infinite.
+ *
+ * @return true if infinite
+ */
+ public boolean isInfinite() {
+ return Float.isInfinite(value);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Increments the value.
+ *
+ * @since Commons Lang 2.2
+ */
+ public void increment() {
+ value++;
+ }
+
+ /**
+ * Decrements the value.
+ *
+ * @since Commons Lang 2.2
+ */
+ public void decrement() {
+ value--;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Adds a value to the value of this instance.
+ *
+ * @param operand the value to add, not null
+ * @since Commons Lang 2.2
+ */
+ public void add(float operand) {
+ this.value += operand;
+ }
+
+ /**
+ * Adds a value to the value of this instance.
+ *
+ * @param operand the value to add, not null
+ * @throws NullPointerException if the object is null
+ * @since Commons Lang 2.2
+ */
+ public void add(Number operand) {
+ this.value += operand.floatValue();
+ }
+
+ /**
+ * Subtracts a value from the value of this instance.
+ *
+ * @param operand the value to subtract
+ * @since Commons Lang 2.2
+ */
+ public void subtract(float operand) {
+ this.value -= operand;
+ }
+
+ /**
+ * Subtracts a value from the value of this instance.
+ *
+ * @param operand the value to subtract, not null
+ * @throws NullPointerException if the object is null
+ * @since Commons Lang 2.2
+ */
+ public void subtract(Number operand) {
+ this.value -= operand.floatValue();
+ }
+
+ //-----------------------------------------------------------------------
+ // shortValue and bytValue rely on Number implementation
+ /**
+ * Returns the value of this MutableFloat as an int.
+ *
+ * @return the numeric value represented by this object after conversion to type int.
+ */
+ public int intValue() {
+ return (int) value;
+ }
+
+ /**
+ * Returns the value of this MutableFloat as a long.
+ *
+ * @return the numeric value represented by this object after conversion to type long.
+ */
+ public long longValue() {
+ return (long) value;
+ }
+
+ /**
+ * Returns the value of this MutableFloat as a float.
+ *
+ * @return the numeric value represented by this object after conversion to type float.
+ */
+ public float floatValue() {
+ return value;
+ }
+
+ /**
+ * Returns the value of this MutableFloat as a double.
+ *
+ * @return the numeric value represented by this object after conversion to type double.
+ */
+ public double doubleValue() {
+ return value;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets this mutable as an instance of Float.
+ *
+ * @return a Float instance containing the value from this mutable, never null
+ */
+ public Float toFloat() {
+ return new Float(floatValue());
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Compares this object against some other object. The result is true
if and only if the argument is
+ * not null
and is a Float
object that represents a float
that has the
+ * identical bit pattern to the bit pattern of the float
represented by this object. For this
+ * purpose, two float values are considered to be the same if and only if the method
+ * {@link Float#floatToIntBits(float)}returns the same int value when applied to each.
+ *
+ * Note that in most cases, for two instances of class Float
,f1
and f2
,
+ * the value of f1.equals(f2)
is true
if and only if
+ *
+ *
+ * f1.floatValue() == f2.floatValue()
+ *
+ *
+ *
+ *
+ * also has the value true
. However, there are two exceptions:
+ *
+ * - If
f1
and f2
both represent Float.NaN
, then the
+ * equals
method returns true
, even though Float.NaN==Float.NaN
has
+ * the value false
.
+ * - If
f1
represents +0.0f
while f2
represents -0.0f
,
+ * or vice versa, the equal
test has the value false
, even though
+ * 0.0f==-0.0f
has the value true
.
+ *
+ * This definition allows hashtables to operate properly.
+ *
+ * @param obj the object to compare with, null returns false
+ * @return true
if the objects are the same; false
otherwise.
+ * @see java.lang.Float#floatToIntBits(float)
+ */
+ public boolean equals(Object obj) {
+ return (obj instanceof MutableFloat)
+ && (Float.floatToIntBits(((MutableFloat) obj).value) == Float.floatToIntBits(value));
+ }
+
+ /**
+ * Returns a suitable hash code for this mutable.
+ *
+ * @return a suitable hash code
+ */
+ public int hashCode() {
+ return Float.floatToIntBits(value);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Compares this mutable to another in ascending order.
+ *
+ * @param obj the other mutable to compare to, not null
+ * @return negative if this is less, zero if equal, positive if greater
+ */
+ public int compareTo(Object obj) {
+ MutableFloat other = (MutableFloat) obj;
+ float anotherVal = other.value;
+ return NumberUtils.compare(value, anotherVal);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Returns the String value of this mutable.
+ *
+ * @return the mutable value as a string
+ */
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/MutableInt.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/MutableInt.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/MutableInt.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,268 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang.mutable;
+
+/**
+ * A mutable int
wrapper.
+ *
+ * @see Integer
+ * @since 2.1
+ * @author Apache Software Foundation
+ * @version $Id$
+ */
+public class MutableInt extends Number implements Comparable, Mutable {
+
+ /**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = 512176391864L;
+
+ /** The mutable value. */
+ private int value;
+
+ /**
+ * Constructs a new MutableInt with the default value of zero.
+ */
+ public MutableInt() {
+ super();
+ }
+
+ /**
+ * Constructs a new MutableInt with the specified value.
+ *
+ * @param value the initial value to store
+ */
+ public MutableInt(int value) {
+ super();
+ this.value = value;
+ }
+
+ /**
+ * Constructs a new MutableInt with the specified value.
+ *
+ * @param value the initial value to store, not null
+ * @throws NullPointerException if the object is null
+ */
+ public MutableInt(Number value) {
+ super();
+ this.value = value.intValue();
+ }
+
+ /**
+ * Constructs a new MutableInt parsing the given string.
+ *
+ * @param value the string to parse, not null
+ * @throws NumberFormatException if the string cannot be parsed into an int
+ * @since 2.5
+ */
+ public MutableInt(String value) throws NumberFormatException {
+ super();
+ this.value = Integer.parseInt(value);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the value as a Integer instance.
+ *
+ * @return the value as a Integer, never null
+ */
+ public Object getValue() {
+ return new Integer(this.value);
+ }
+
+ /**
+ * Sets the value.
+ *
+ * @param value the value to set
+ */
+ public void setValue(int value) {
+ this.value = value;
+ }
+
+ /**
+ * Sets the value from any Number instance.
+ *
+ * @param value the value to set, not null
+ * @throws NullPointerException if the object is null
+ * @throws ClassCastException if the type is not a {@link Number}
+ */
+ public void setValue(Object value) {
+ setValue(((Number) value).intValue());
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Increments the value.
+ *
+ * @since Commons Lang 2.2
+ */
+ public void increment() {
+ value++;
+ }
+
+ /**
+ * Decrements the value.
+ *
+ * @since Commons Lang 2.2
+ */
+ public void decrement() {
+ value--;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Adds a value to the value of this instance.
+ *
+ * @param operand the value to add, not null
+ * @since Commons Lang 2.2
+ */
+ public void add(int operand) {
+ this.value += operand;
+ }
+
+ /**
+ * Adds a value to the value of this instance.
+ *
+ * @param operand the value to add, not null
+ * @throws NullPointerException if the object is null
+ * @since Commons Lang 2.2
+ */
+ public void add(Number operand) {
+ this.value += operand.intValue();
+ }
+
+ /**
+ * Subtracts a value from the value of this instance.
+ *
+ * @param operand the value to subtract, not null
+ * @since Commons Lang 2.2
+ */
+ public void subtract(int operand) {
+ this.value -= operand;
+ }
+
+ /**
+ * Subtracts a value from the value of this instance.
+ *
+ * @param operand the value to subtract, not null
+ * @throws NullPointerException if the object is null
+ * @since Commons Lang 2.2
+ */
+ public void subtract(Number operand) {
+ this.value -= operand.intValue();
+ }
+
+ //-----------------------------------------------------------------------
+ // shortValue and bytValue rely on Number implementation
+ /**
+ * Returns the value of this MutableInt as an int.
+ *
+ * @return the numeric value represented by this object after conversion to type int.
+ */
+ public int intValue() {
+ return value;
+ }
+
+ /**
+ * Returns the value of this MutableInt as a long.
+ *
+ * @return the numeric value represented by this object after conversion to type long.
+ */
+ public long longValue() {
+ return value;
+ }
+
+ /**
+ * Returns the value of this MutableInt as a float.
+ *
+ * @return the numeric value represented by this object after conversion to type float.
+ */
+ public float floatValue() {
+ return value;
+ }
+
+ /**
+ * Returns the value of this MutableInt as a double.
+ *
+ * @return the numeric value represented by this object after conversion to type double.
+ */
+ public double doubleValue() {
+ return value;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets this mutable as an instance of Integer.
+ *
+ * @return a Integer instance containing the value from this mutable, never null
+ */
+ public Integer toInteger() {
+ return new Integer(intValue());
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Compares this object to the specified object. The result is true
if and only if the argument is
+ * not null
and is a MutableInt
object that contains the same int
value
+ * as this object.
+ *
+ * @param obj the object to compare with, null returns false
+ * @return true
if the objects are the same; false
otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (obj instanceof MutableInt) {
+ return value == ((MutableInt) obj).intValue();
+ }
+ return false;
+ }
+
+ /**
+ * Returns a suitable hash code for this mutable.
+ *
+ * @return a suitable hash code
+ */
+ public int hashCode() {
+ return value;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Compares this mutable to another in ascending order.
+ *
+ * @param obj the other mutable to compare to, not null
+ * @return negative if this is less, zero if equal, positive if greater
+ * @throws ClassCastException if the argument is not a MutableInt
+ */
+ public int compareTo(Object obj) {
+ MutableInt other = (MutableInt) obj;
+ int anotherVal = other.value;
+ return value < anotherVal ? -1 : (value == anotherVal ? 0 : 1);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Returns the String value of this mutable.
+ *
+ * @return the mutable value as a string
+ */
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/MutableLong.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/MutableLong.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/MutableLong.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,268 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang.mutable;
+
+/**
+ * A mutable long
wrapper.
+ *
+ * @see Long
+ * @since 2.1
+ * @author Apache Software Foundation
+ * @version $Id$
+ */
+public class MutableLong extends Number implements Comparable, Mutable {
+
+ /**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = 62986528375L;
+
+ /** The mutable value. */
+ private long value;
+
+ /**
+ * Constructs a new MutableLong with the default value of zero.
+ */
+ public MutableLong() {
+ super();
+ }
+
+ /**
+ * Constructs a new MutableLong with the specified value.
+ *
+ * @param value the initial value to store
+ */
+ public MutableLong(long value) {
+ super();
+ this.value = value;
+ }
+
+ /**
+ * Constructs a new MutableLong with the specified value.
+ *
+ * @param value the initial value to store, not null
+ * @throws NullPointerException if the object is null
+ */
+ public MutableLong(Number value) {
+ super();
+ this.value = value.longValue();
+ }
+
+ /**
+ * Constructs a new MutableLong parsing the given string.
+ *
+ * @param value the string to parse, not null
+ * @throws NumberFormatException if the string cannot be parsed into a long
+ * @since 2.5
+ */
+ public MutableLong(String value) throws NumberFormatException {
+ super();
+ this.value = Long.parseLong(value);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the value as a Long instance.
+ *
+ * @return the value as a Long, never null
+ */
+ public Object getValue() {
+ return new Long(this.value);
+ }
+
+ /**
+ * Sets the value.
+ *
+ * @param value the value to set
+ */
+ public void setValue(long value) {
+ this.value = value;
+ }
+
+ /**
+ * Sets the value from any Number instance.
+ *
+ * @param value the value to set, not null
+ * @throws NullPointerException if the object is null
+ * @throws ClassCastException if the type is not a {@link Number}
+ */
+ public void setValue(Object value) {
+ setValue(((Number) value).longValue());
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Increments the value.
+ *
+ * @since Commons Lang 2.2
+ */
+ public void increment() {
+ value++;
+ }
+
+ /**
+ * Decrements the value.
+ *
+ * @since Commons Lang 2.2
+ */
+ public void decrement() {
+ value--;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Adds a value to the value of this instance.
+ *
+ * @param operand the value to add, not null
+ * @since Commons Lang 2.2
+ */
+ public void add(long operand) {
+ this.value += operand;
+ }
+
+ /**
+ * Adds a value to the value of this instance.
+ *
+ * @param operand the value to add, not null
+ * @throws NullPointerException if the object is null
+ * @since Commons Lang 2.2
+ */
+ public void add(Number operand) {
+ this.value += operand.longValue();
+ }
+
+ /**
+ * Subtracts a value from the value of this instance.
+ *
+ * @param operand the value to subtract, not null
+ * @since Commons Lang 2.2
+ */
+ public void subtract(long operand) {
+ this.value -= operand;
+ }
+
+ /**
+ * Subtracts a value from the value of this instance.
+ *
+ * @param operand the value to subtract, not null
+ * @throws NullPointerException if the object is null
+ * @since Commons Lang 2.2
+ */
+ public void subtract(Number operand) {
+ this.value -= operand.longValue();
+ }
+
+ //-----------------------------------------------------------------------
+ // shortValue and bytValue rely on Number implementation
+ /**
+ * Returns the value of this MutableLong as an int.
+ *
+ * @return the numeric value represented by this object after conversion to type int.
+ */
+ public int intValue() {
+ return (int) value;
+ }
+
+ /**
+ * Returns the value of this MutableLong as a long.
+ *
+ * @return the numeric value represented by this object after conversion to type long.
+ */
+ public long longValue() {
+ return value;
+ }
+
+ /**
+ * Returns the value of this MutableLong as a float.
+ *
+ * @return the numeric value represented by this object after conversion to type float.
+ */
+ public float floatValue() {
+ return value;
+ }
+
+ /**
+ * Returns the value of this MutableLong as a double.
+ *
+ * @return the numeric value represented by this object after conversion to type double.
+ */
+ public double doubleValue() {
+ return value;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets this mutable as an instance of Long.
+ *
+ * @return a Long instance containing the value from this mutable, never null
+ */
+ public Long toLong() {
+ return new Long(longValue());
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Compares this object to the specified object. The result is true
if and only if the argument
+ * is not null
and is a MutableLong
object that contains the same long
+ * value as this object.
+ *
+ * @param obj the object to compare with, null returns false
+ * @return true
if the objects are the same; false
otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (obj instanceof MutableLong) {
+ return value == ((MutableLong) obj).longValue();
+ }
+ return false;
+ }
+
+ /**
+ * Returns a suitable hash code for this mutable.
+ *
+ * @return a suitable hash code
+ */
+ public int hashCode() {
+ return (int) (value ^ (value >>> 32));
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Compares this mutable to another in ascending order.
+ *
+ * @param obj the other mutable to compare to, not null
+ * @return negative if this is less, zero if equal, positive if greater
+ * @throws ClassCastException if the argument is not a MutableLong
+ */
+ public int compareTo(Object obj) {
+ MutableLong other = (MutableLong) obj;
+ long anotherVal = other.value;
+ return value < anotherVal ? -1 : (value == anotherVal ? 0 : 1);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Returns the String value of this mutable.
+ *
+ * @return the mutable value as a string
+ */
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/MutableObject.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/MutableObject.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/MutableObject.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.commons.lang.mutable;
+
+import java.io.Serializable;
+
+/**
+ * A mutable Object
wrapper.
+ *
+ * @since 2.1
+ * @author Apache Software Foundation
+ * @version $Id$
+ */
+public class MutableObject implements Mutable, Serializable {
+
+ /**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = 86241875189L;
+
+ /** The mutable value. */
+ private Object value;
+
+ /**
+ * Constructs a new MutableObject with the default value of null
.
+ */
+ public MutableObject() {
+ super();
+ }
+
+ /**
+ * Constructs a new MutableObject with the specified value.
+ *
+ * @param value the initial value to store
+ */
+ public MutableObject(Object value) {
+ super();
+ this.value = value;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the value.
+ *
+ * @return the value, may be null
+ */
+ public Object getValue() {
+ return this.value;
+ }
+
+ /**
+ * Sets the value.
+ *
+ * @param value the value to set
+ */
+ public void setValue(Object value) {
+ this.value = value;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Compares this object against the specified object. The result is true
if and only if the argument
+ * is not null
and is a MutableObject
object that contains the same Object
+ * value as this object.
+ *
+ * @param obj the object to compare with, null returns false
+ * @return true
if the objects are the same; false
otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (obj instanceof MutableObject) {
+ Object other = ((MutableObject) obj).value;
+ return value == other || (value != null && value.equals(other));
+ }
+ return false;
+ }
+
+ /**
+ * Returns the value's hash code or 0
if the value is null
.
+ *
+ * @return the value's hash code or 0
if the value is null
.
+ */
+ public int hashCode() {
+ return value == null ? 0 : value.hashCode();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Returns the String value of this mutable.
+ *
+ * @return the mutable value as a string
+ */
+ public String toString() {
+ return value == null ? "null" : value.toString();
+ }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/MutableShort.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/MutableShort.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/MutableShort.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,277 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang.mutable;
+
+/**
+ * A mutable short
wrapper.
+ *
+ * @see Short
+ * @since 2.1
+ * @author Apache Software Foundation
+ * @version $Id$
+ */
+public class MutableShort extends Number implements Comparable, Mutable {
+
+ /**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = -2135791679L;
+
+ /** The mutable value. */
+ private short value;
+
+ /**
+ * Constructs a new MutableShort with the default value of zero.
+ */
+ public MutableShort() {
+ super();
+ }
+
+ /**
+ * Constructs a new MutableShort with the specified value.
+ *
+ * @param value the initial value to store
+ */
+ public MutableShort(short value) {
+ super();
+ this.value = value;
+ }
+
+ /**
+ * Constructs a new MutableShort with the specified value.
+ *
+ * @param value the initial value to store, not null
+ * @throws NullPointerException if the object is null
+ */
+ public MutableShort(Number value) {
+ super();
+ this.value = value.shortValue();
+ }
+
+ /**
+ * Constructs a new MutableShort parsing the given string.
+ *
+ * @param value the string to parse, not null
+ * @throws NumberFormatException if the string cannot be parsed into a short
+ * @since 2.5
+ */
+ public MutableShort(String value) throws NumberFormatException {
+ super();
+ this.value = Short.parseShort(value);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the value as a Short instance.
+ *
+ * @return the value as a Short, never null
+ */
+ public Object getValue() {
+ return new Short(this.value);
+ }
+
+ /**
+ * Sets the value.
+ *
+ * @param value the value to set
+ */
+ public void setValue(short value) {
+ this.value = value;
+ }
+
+ /**
+ * Sets the value from any Number instance.
+ *
+ * @param value the value to set, not null
+ * @throws NullPointerException if the object is null
+ * @throws ClassCastException if the type is not a {@link Number}
+ */
+ public void setValue(Object value) {
+ setValue(((Number) value).shortValue());
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Increments the value.
+ *
+ * @since Commons Lang 2.2
+ */
+ public void increment() {
+ value++;
+ }
+
+ /**
+ * Decrements the value.
+ *
+ * @since Commons Lang 2.2
+ */
+ public void decrement() {
+ value--;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Adds a value to the value of this instance.
+ *
+ * @param operand the value to add, not null
+ * @since Commons Lang 2.2
+ */
+ public void add(short operand) {
+ this.value += operand;
+ }
+
+ /**
+ * Adds a value to the value of this instance.
+ *
+ * @param operand the value to add, not null
+ * @throws NullPointerException if the object is null
+ * @since Commons Lang 2.2
+ */
+ public void add(Number operand) {
+ this.value += operand.shortValue();
+ }
+
+ /**
+ * Subtracts a value from the value of this instance.
+ *
+ * @param operand the value to subtract, not null
+ * @since Commons Lang 2.2
+ */
+ public void subtract(short operand) {
+ this.value -= operand;
+ }
+
+ /**
+ * Subtracts a value from the value of this instance.
+ *
+ * @param operand the value to subtract, not null
+ * @throws NullPointerException if the object is null
+ * @since Commons Lang 2.2
+ */
+ public void subtract(Number operand) {
+ this.value -= operand.shortValue();
+ }
+
+ //-----------------------------------------------------------------------
+ // bytValue relies on Number implementation
+ /**
+ * Returns the value of this MutableShort as a short.
+ *
+ * @return the numeric value represented by this object after conversion to type short.
+ */
+ public short shortValue() {
+ return value;
+ }
+
+ /**
+ * Returns the value of this MutableShort as an int.
+ *
+ * @return the numeric value represented by this object after conversion to type int.
+ */
+ public int intValue() {
+ return value;
+ }
+
+ /**
+ * Returns the value of this MutableShort as a long.
+ *
+ * @return the numeric value represented by this object after conversion to type long.
+ */
+ public long longValue() {
+ return value;
+ }
+
+ /**
+ * Returns the value of this MutableShort as a float.
+ *
+ * @return the numeric value represented by this object after conversion to type float.
+ */
+ public float floatValue() {
+ return value;
+ }
+
+ /**
+ * Returns the value of this MutableShort as a double.
+ *
+ * @return the numeric value represented by this object after conversion to type double.
+ */
+ public double doubleValue() {
+ return value;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets this mutable as an instance of Short.
+ *
+ * @return a Short instance containing the value from this mutable, never null
+ */
+ public Short toShort() {
+ return new Short(shortValue());
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Compares this object to the specified object. The result is true
if and only if the argument
+ * is not null
and is a MutableShort
object that contains the same short
+ * value as this object.
+ *
+ * @param obj the object to compare with, null returns false
+ * @return true
if the objects are the same; false
otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (obj instanceof MutableShort) {
+ return value == ((MutableShort) obj).shortValue();
+ }
+ return false;
+ }
+
+ /**
+ * Returns a suitable hash code for this mutable.
+ *
+ * @return a suitable hash code
+ */
+ public int hashCode() {
+ return value;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Compares this mutable to another in ascending order.
+ *
+ * @param obj the other mutable to compare to, not null
+ * @return negative if this is less, zero if equal, positive if greater
+ * @throws ClassCastException if the argument is not a MutableShort
+ */
+ public int compareTo(Object obj) {
+ MutableShort other = (MutableShort) obj;
+ short anotherVal = other.value;
+ return value < anotherVal ? -1 : (value == anotherVal ? 0 : 1);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Returns the String value of this mutable.
+ *
+ * @return the mutable value as a string
+ */
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/package.html
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/package.html (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/mutable/package.html (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+Provides typed mutable wrappers to primitive values and Object.
+@since 2.1
+These classes are not thread-safe.
+
+
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/overview.html
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/overview.html (.../overview.html) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/overview.html (.../overview.html) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,7 +1,23 @@
+
-This document is the API specification for the Apache Jakarta Commons Lang Library, version 2.0.
+This document is the API specification for the Apache Commons Lang library.
-
\ No newline at end of file
+
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/package.html
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/package.html (.../package.html) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/package.html (.../package.html) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,7 +1,25 @@
+
Provides highly reusable static utility methods, chiefly concerned
-with adding value to java.lang
and other standard core classes.
+with adding value to the {@link java.lang} classes.
@since 1.0
+Most of these classes are immutable and thus thread-safe.
+However Charset is not currently guaranteed thread-safe under all circumstances.
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/reflect/ConstructorUtils.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/reflect/ConstructorUtils.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/reflect/ConstructorUtils.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,353 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang.reflect;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.ClassUtils;
+
+/**
+ * Utility reflection methods focussed on constructors, modelled after
+ * {@link MethodUtils}.
+ *
+ * Known Limitations
Accessing Public Constructors In A Default
+ * Access Superclass
There is an issue when invoking public constructors
+ * contained in a default access superclass. Reflection locates these
+ * constructors fine and correctly assigns them as public. However, an
+ * IllegalAccessException
is thrown if the constructors is
+ * invoked.
+ *
+ * ConstructorUtils
contains a workaround for this situation. It
+ * will attempt to call setAccessible
on this constructor. If this
+ * call succeeds, then the method can be invoked as normal. This call will only
+ * succeed when the application has sufficient security privilages. If this call
+ * fails then a warning will be logged and the method may fail.
+ *
+ * @author Apache Software Foundation
+ * @author Craig R. McClanahan
+ * @author Ralph Schaer
+ * @author Chris Audley
+ * @author Rey Francois
+ * @author Gregor Rayman
+ * @author Jan Sorensen
+ * @author Robert Burrell Donkin
+ * @author Rodney Waldhoff
+ * @since 2.5
+ * @version $Id$
+ */
+public class ConstructorUtils {
+
+ /**
+ * ConstructorUtils instances should NOT be constructed in standard
+ * programming. Instead, the class should be used as
+ * ConstructorUtils.invokeConstructor(cls, args)
.
+ *
+ * This constructor is public to permit tools that require a JavaBean
+ * instance to operate.
+ */
+ public ConstructorUtils() {
+ super();
+ }
+
+ /**
+ * Returns new instance of klazz
created using the actual
+ * arguments args
. The formal parameter types are inferred from
+ * the actual values of args
. See
+ * {@link #invokeExactConstructor(Class, Object[], Class[])} for more
+ * details.
+ *
+ * The signatures should be assignment compatible.
+ *
+ * @param cls the class to be constructed.
+ * @param arg the actual argument
+ * @return new instance of klazz
+ *
+ * @throws NoSuchMethodException If the constructor cannot be found
+ * @throws IllegalAccessException If an error occurs accessing the constructor
+ * @throws InvocationTargetException If an error occurs invoking the constructor
+ * @throws InstantiationException If an error occurs instantiating the class
+ *
+ * @see #invokeConstructor(java.lang.Class, java.lang.Object[], java.lang.Class[])
+ */
+ public static Object invokeConstructor(Class cls, Object arg)
+ throws NoSuchMethodException, IllegalAccessException,
+ InvocationTargetException, InstantiationException {
+ return invokeConstructor(cls, new Object[] { arg });
+ }
+
+ /**
+ * Returns new instance of klazz
created using the actual
+ * arguments args
. The formal parameter types are inferred from
+ * the actual values of args
. See
+ * {@link #invokeExactConstructor(Class, Object[], Class[])} for more
+ * details.
+ * The signatures should be assignment compatible.
+ *
+ * @param cls the class to be constructed.
+ * @param args actual argument array
+ * @return new instance of klazz
+ *
+ * @throws NoSuchMethodException If the constructor cannot be found
+ * @throws IllegalAccessException If an error occurs accessing the
+ * constructor
+ * @throws InvocationTargetException If an error occurs invoking the
+ * constructor
+ * @throws InstantiationException If an error occurs instantiating the class
+ *
+ * @see #invokeConstructor(java.lang.Class, java.lang.Object[],
+ * java.lang.Class[])
+ */
+ public static Object invokeConstructor(Class cls, Object[] args)
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException,
+ InstantiationException {
+ if (null == args) {
+ args = ArrayUtils.EMPTY_OBJECT_ARRAY;
+ }
+ Class parameterTypes[] = new Class[args.length];
+ for (int i = 0; i < args.length; i++) {
+ parameterTypes[i] = args[i].getClass();
+ }
+ return invokeConstructor(cls, args, parameterTypes);
+ }
+
+ /**
+ * Returns new instance of klazz
created using constructor
+ * with signature parameterTypes
and actual arguments
+ * args
.
+ *
+ * The signatures should be assignment compatible.
+ *
+ * @param cls the class to be constructed.
+ * @param args actual argument array
+ * @param parameterTypes parameter types array
+ * @return new instance of klazz
+ *
+ * @throws NoSuchMethodException if matching constructor cannot be found
+ * @throws IllegalAccessException thrown on the constructor's invocation
+ * @throws InvocationTargetException thrown on the constructor's invocation
+ * @throws InstantiationException thrown on the constructor's invocation
+ * @see Constructor#newInstance
+ */
+ public static Object invokeConstructor(Class cls, Object[] args, Class[] parameterTypes)
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException,
+ InstantiationException {
+ if (parameterTypes == null) {
+ parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
+ }
+ if (args == null) {
+ args = ArrayUtils.EMPTY_OBJECT_ARRAY;
+ }
+ Constructor ctor = getMatchingAccessibleConstructor(cls, parameterTypes);
+ if (null == ctor) {
+ throw new NoSuchMethodException("No such accessible constructor on object: "
+ + cls.getName());
+ }
+ return ctor.newInstance(args);
+ }
+
+ /**
+ * Returns new instance of klazz
created using the actual
+ * arguments args
. The formal parameter types are inferred from
+ * the actual values of args
. See
+ * {@link #invokeExactConstructor(Class, Object[], Class[])} for more
+ * details.
+ *
+ * The signatures should match exactly.
+ *
+ * @param cls the class to be constructed.
+ * @param arg the actual argument
+ * @return new instance of klazz
+ *
+ * @throws NoSuchMethodException If the constructor cannot be found
+ * @throws IllegalAccessException If an error occurs accessing the constructor
+ * @throws InvocationTargetException If an error occurs invoking the constructor
+ * @throws InstantiationException If an error occurs instantiating the class
+ *
+ * @see #invokeExactConstructor(java.lang.Class, java.lang.Object[], java.lang.Class[])
+ */
+ public static Object invokeExactConstructor(Class cls, Object arg)
+ throws NoSuchMethodException, IllegalAccessException,
+ InvocationTargetException, InstantiationException {
+ return invokeExactConstructor(cls, new Object[] { arg });
+ }
+
+ /**
+ * Returns new instance of klazz
created using the actual
+ * arguments args
. The formal parameter types are inferred from
+ * the actual values of args
. See
+ * {@link #invokeExactConstructor(Class, Object[], Class[])} for more
+ * details.
+ *
+ * The signatures should match exactly.
+ *
+ * @param cls the class to be constructed.
+ * @param args actual argument array
+ * @return new instance of klazz
+ *
+ * @throws NoSuchMethodException If the constructor cannot be found
+ * @throws IllegalAccessException If an error occurs accessing the
+ * constructor
+ * @throws InvocationTargetException If an error occurs invoking the
+ * constructor
+ * @throws InstantiationException If an error occurs instantiating the class
+ *
+ * @see #invokeExactConstructor(java.lang.Class, java.lang.Object[],
+ * java.lang.Class[])
+ */
+ public static Object invokeExactConstructor(Class cls, Object[] args)
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException,
+ InstantiationException {
+ if (null == args) {
+ args = ArrayUtils.EMPTY_OBJECT_ARRAY;
+ }
+ int arguments = args.length;
+ Class parameterTypes[] = new Class[arguments];
+ for (int i = 0; i < arguments; i++) {
+ parameterTypes[i] = args[i].getClass();
+ }
+ return invokeExactConstructor(cls, args, parameterTypes);
+ }
+
+ /**
+ * Returns new instance of klazz
created using constructor
+ * with signature parameterTypes
and actual arguments
+ * args
.
+ *
+ * The signatures should match exactly.
+ *
+ * @param cls the class to be constructed.
+ * @param args actual argument array
+ * @param parameterTypes parameter types array
+ * @return new instance of klazz
+ *
+ * @throws NoSuchMethodException if matching constructor cannot be found
+ * @throws IllegalAccessException thrown on the constructor's invocation
+ * @throws InvocationTargetException thrown on the constructor's invocation
+ * @throws InstantiationException thrown on the constructor's invocation
+ * @see Constructor#newInstance
+ */
+ public static Object invokeExactConstructor(Class cls, Object[] args,
+ Class[] parameterTypes) throws NoSuchMethodException, IllegalAccessException,
+ InvocationTargetException, InstantiationException {
+ if (args == null) {
+ args = ArrayUtils.EMPTY_OBJECT_ARRAY;
+ }
+ if (parameterTypes == null) {
+ parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
+ }
+ Constructor ctor = getAccessibleConstructor(cls, parameterTypes);
+ if (null == ctor) {
+ throw new NoSuchMethodException("No such accessible constructor on object: "
+ + cls.getName());
+ }
+ return ctor.newInstance(args);
+ }
+
+ /**
+ * Returns a constructor with single argument.
+ * @param cls the class to be constructed
+ * @param parameterType The constructor parameter type
+ * @return null if matching accessible constructor can not be found.
+ * @see Class#getConstructor
+ * @see #getAccessibleConstructor(java.lang.reflect.Constructor)
+ */
+ public static Constructor getAccessibleConstructor(Class cls,
+ Class parameterType) {
+ return getAccessibleConstructor(cls, new Class[] { parameterType });
+ }
+
+ /**
+ * Returns a constructor given a class and signature.
+ * @param cls the class to be constructed
+ * @param parameterTypes the parameter array
+ * @return null if matching accessible constructor can not be found
+ * @see Class#getConstructor
+ * @see #getAccessibleConstructor(java.lang.reflect.Constructor)
+ */
+ public static Constructor getAccessibleConstructor(Class cls,
+ Class[] parameterTypes) {
+ try {
+ return getAccessibleConstructor(cls.getConstructor(parameterTypes));
+ } catch (NoSuchMethodException e) {
+ return (null);
+ }
+ }
+
+ /**
+ * Returns accessible version of the given constructor.
+ * @param ctor prototype constructor object.
+ * @return null
if accessible constructor can not be found.
+ * @see java.lang.SecurityManager
+ */
+ public static Constructor getAccessibleConstructor(Constructor ctor) {
+ return MemberUtils.isAccessible(ctor)
+ && Modifier.isPublic(ctor.getDeclaringClass().getModifiers()) ? ctor : null;
+ }
+
+ /**
+ * Find an accessible constructor with compatible parameters. Compatible
+ * parameters mean that every method parameter is assignable from the given
+ * parameters. In other words, it finds constructor that will take the
+ * parameters given.
+ *
+ * First it checks if there is constructor matching the exact signature.
+ * If no such, all the constructors of the class are tested if their
+ * signatures are assignment compatible with the parameter types. The first
+ * matching constructor is returned.
+ *
+ * @param cls find constructor for this class
+ * @param parameterTypes find method with compatible parameters
+ * @return a valid Constructor object. If there's no matching constructor,
+ * returns null
.
+ */
+ public static Constructor getMatchingAccessibleConstructor(Class cls,
+ Class[] parameterTypes) {
+ // see if we can find the constructor directly
+ // most of the time this works and it's much faster
+ try {
+ Constructor ctor = cls.getConstructor(parameterTypes);
+ MemberUtils.setAccessibleWorkaround(ctor);
+ return ctor;
+ } catch (NoSuchMethodException e) { /* SWALLOW */
+ }
+ Constructor result = null;
+ // search through all constructors
+ Constructor[] ctors = cls.getConstructors();
+ // return best match:
+ for (int i = 0; i < ctors.length; i++) {
+
+ // compare parameters
+ if (ClassUtils.isAssignable(parameterTypes, ctors[i].getParameterTypes(), true)) {
+ // get accessible version of constructor
+ Constructor ctor = getAccessibleConstructor(ctors[i]);
+ if (ctor != null) {
+ MemberUtils.setAccessibleWorkaround(ctor);
+ if (result == null
+ || MemberUtils.compareParameterTypes(ctor.getParameterTypes(), result
+ .getParameterTypes(), parameterTypes) < 0) {
+ result = ctor;
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/reflect/FieldUtils.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/reflect/FieldUtils.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/reflect/FieldUtils.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,599 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang.reflect;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Iterator;
+
+import org.apache.commons.lang.ClassUtils;
+
+/**
+ * Utilities for working with fields by reflection. Adapted and refactored
+ * from the dormant [reflect] Commons sandbox component.
+ *
+ * The ability is provided to break the scoping restrictions coded by the
+ * programmer. This can allow fields to be changed that shouldn't be. This
+ * facility should be used with care.
+ *
+ * @author Apache Software Foundation
+ * @author Matt Benson
+ * @since 2.5
+ * @version $Id$
+ */
+public class FieldUtils {
+
+ /**
+ * FieldUtils instances should NOT be constructed in standard programming.
+ *
+ * This constructor is public to permit tools that require a JavaBean instance
+ * to operate.
+ */
+ public FieldUtils() {
+ super();
+ }
+
+ /**
+ * Gets an accessible Field
by name respecting scope.
+ * Superclasses/interfaces will be considered.
+ *
+ * @param cls the class to reflect, must not be null
+ * @param fieldName the field name to obtain
+ * @return the Field object
+ * @throws IllegalArgumentException if the class or field name is null
+ */
+ public static Field getField(Class cls, String fieldName) {
+ Field field = getField(cls, fieldName, false);
+ MemberUtils.setAccessibleWorkaround(field);
+ return field;
+ }
+
+ /**
+ * Gets an accessible Field
by name breaking scope
+ * if requested. Superclasses/interfaces will be considered.
+ *
+ * @param cls the class to reflect, must not be null
+ * @param fieldName the field name to obtain
+ * @param forceAccess whether to break scope restrictions using the
+ * setAccessible
method. False
will only
+ * match public fields.
+ * @return the Field object
+ * @throws IllegalArgumentException if the class or field name is null
+ */
+ public static Field getField(final Class cls, String fieldName, boolean forceAccess) {
+ if (cls == null) {
+ throw new IllegalArgumentException("The class must not be null");
+ }
+ if (fieldName == null) {
+ throw new IllegalArgumentException("The field name must not be null");
+ }
+ // Sun Java 1.3 has a bugged implementation of getField hence we write the
+ // code ourselves
+
+ // getField() will return the Field object with the declaring class
+ // set correctly to the class that declares the field. Thus requesting the
+ // field on a subclass will return the field from the superclass.
+ //
+ // priority order for lookup:
+ // searchclass private/protected/package/public
+ // superclass protected/package/public
+ // private/different package blocks access to further superclasses
+ // implementedinterface public
+
+ // check up the superclass hierarchy
+ for (Class acls = cls; acls != null; acls = acls.getSuperclass()) {
+ try {
+ Field field = acls.getDeclaredField(fieldName);
+ // getDeclaredField checks for non-public scopes as well
+ // and it returns accurate results
+ if (!Modifier.isPublic(field.getModifiers())) {
+ if (forceAccess) {
+ field.setAccessible(true);
+ } else {
+ continue;
+ }
+ }
+ return field;
+ } catch (NoSuchFieldException ex) {
+ // ignore
+ }
+ }
+ // check the public interface case. This must be manually searched for
+ // incase there is a public supersuperclass field hidden by a private/package
+ // superclass field.
+ Field match = null;
+ for (Iterator intf = ClassUtils.getAllInterfaces(cls).iterator(); intf
+ .hasNext();) {
+ try {
+ Field test = ((Class) intf.next()).getField(fieldName);
+ if (match != null) {
+ throw new IllegalArgumentException(
+ "Reference to field "
+ + fieldName
+ + " is ambiguous relative to "
+ + cls
+ + "; a matching field exists on two or more implemented interfaces.");
+ }
+ match = test;
+ } catch (NoSuchFieldException ex) {
+ // ignore
+ }
+ }
+ return match;
+ }
+
+ /**
+ * Gets an accessible Field
by name respecting scope.
+ * Only the specified class will be considered.
+ *
+ * @param cls the class to reflect, must not be null
+ * @param fieldName the field name to obtain
+ * @return the Field object
+ * @throws IllegalArgumentException if the class or field name is null
+ */
+ public static Field getDeclaredField(Class cls, String fieldName) {
+ return getDeclaredField(cls, fieldName, false);
+ }
+
+ /**
+ * Gets an accessible Field
by name breaking scope
+ * if requested. Only the specified class will be considered.
+ *
+ * @param cls the class to reflect, must not be null
+ * @param fieldName the field name to obtain
+ * @param forceAccess whether to break scope restrictions using the
+ * setAccessible
method. False will only match public fields.
+ * @return the Field object
+ * @throws IllegalArgumentException if the class or field name is null
+ */
+ public static Field getDeclaredField(Class cls, String fieldName, boolean forceAccess) {
+ if (cls == null) {
+ throw new IllegalArgumentException("The class must not be null");
+ }
+ if (fieldName == null) {
+ throw new IllegalArgumentException("The field name must not be null");
+ }
+ try {
+ // only consider the specified class by using getDeclaredField()
+ Field field = cls.getDeclaredField(fieldName);
+ if (!MemberUtils.isAccessible(field)) {
+ if (forceAccess) {
+ field.setAccessible(true);
+ } else {
+ return null;
+ }
+ }
+ return field;
+ } catch (NoSuchFieldException e) {
+ }
+ return null;
+ }
+
+ /**
+ * Read an accessible static Field.
+ * @param field to read
+ * @return the field value
+ * @throws IllegalArgumentException if the field is null or not static
+ * @throws IllegalAccessException if the field is not accessible
+ */
+ public static Object readStaticField(Field field) throws IllegalAccessException {
+ return readStaticField(field, false);
+ }
+
+ /**
+ * Read a static Field.
+ * @param field to read
+ * @param forceAccess whether to break scope restrictions using the
+ * setAccessible
method.
+ * @return the field value
+ * @throws IllegalArgumentException if the field is null or not static
+ * @throws IllegalAccessException if the field is not made accessible
+ */
+ public static Object readStaticField(Field field, boolean forceAccess) throws IllegalAccessException {
+ if (field == null) {
+ throw new IllegalArgumentException("The field must not be null");
+ }
+ if (!Modifier.isStatic(field.getModifiers())) {
+ throw new IllegalArgumentException("The field '" + field.getName() + "' is not static");
+ }
+ return readField(field, (Object) null, forceAccess);
+ }
+
+ /**
+ * Read the named public static field. Superclasses will be considered.
+ * @param cls the class to reflect, must not be null
+ * @param fieldName the field name to obtain
+ * @return the value of the field
+ * @throws IllegalArgumentException if the class or field name is null
+ * @throws IllegalAccessException if the field is not accessible
+ */
+ public static Object readStaticField(Class cls, String fieldName) throws IllegalAccessException {
+ return readStaticField(cls, fieldName, false);
+ }
+
+ /**
+ * Read the named static field. Superclasses will be considered.
+ * @param cls the class to reflect, must not be null
+ * @param fieldName the field name to obtain
+ * @param forceAccess whether to break scope restrictions using the
+ * setAccessible
method. False
will only
+ * match public fields.
+ * @return the Field object
+ * @throws IllegalArgumentException if the class or field name is null
+ * @throws IllegalAccessException if the field is not made accessible
+ */
+ public static Object readStaticField(Class cls, String fieldName, boolean forceAccess) throws IllegalAccessException {
+ Field field = getField(cls, fieldName, forceAccess);
+ if (field == null) {
+ throw new IllegalArgumentException("Cannot locate field " + fieldName + " on " + cls);
+ }
+ //already forced access above, don't repeat it here:
+ return readStaticField(field, false);
+ }
+
+ /**
+ * Gets a static Field value by name. The field must be public.
+ * Only the specified class will be considered.
+ *
+ * @param cls the class to reflect, must not be null
+ * @param fieldName the field name to obtain
+ * @return the value of the field
+ * @throws IllegalArgumentException if the class or field name is null
+ * @throws IllegalAccessException if the field is not accessible
+ */
+ public static Object readDeclaredStaticField(Class cls, String fieldName) throws IllegalAccessException {
+ return readDeclaredStaticField(cls, fieldName, false);
+ }
+
+ /**
+ * Gets a static Field value by name. Only the specified class will
+ * be considered.
+ *
+ * @param cls the class to reflect, must not be null
+ * @param fieldName the field name to obtain
+ * @param forceAccess whether to break scope restrictions using the
+ * setAccessible
method. False
will only
+ * match public fields.
+ * @return the Field object
+ * @throws IllegalArgumentException if the class or field name is null
+ * @throws IllegalAccessException if the field is not made accessible
+ */
+ public static Object readDeclaredStaticField(Class cls, String fieldName, boolean forceAccess)
+ throws IllegalAccessException {
+ Field field = getDeclaredField(cls, fieldName, forceAccess);
+ if (field == null) {
+ throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName);
+ }
+ //already forced access above, don't repeat it here:
+ return readStaticField(field, false);
+ }
+
+ /**
+ * Read an accessible Field.
+ * @param field the field to use
+ * @param target the object to call on, may be null for static fields
+ * @return the field value
+ * @throws IllegalArgumentException if the field is null
+ * @throws IllegalAccessException if the field is not accessible
+ */
+ public static Object readField(Field field, Object target) throws IllegalAccessException {
+ return readField(field, target, false);
+ }
+
+ /**
+ * Read a Field.
+ * @param field the field to use
+ * @param target the object to call on, may be null for static fields
+ * @param forceAccess whether to break scope restrictions using the
+ * setAccessible
method.
+ * @return the field value
+ * @throws IllegalArgumentException if the field is null
+ * @throws IllegalAccessException if the field is not made accessible
+ */
+ public static Object readField(Field field, Object target, boolean forceAccess) throws IllegalAccessException {
+ if (field == null) {
+ throw new IllegalArgumentException("The field must not be null");
+ }
+ if (forceAccess && !field.isAccessible()) {
+ field.setAccessible(true);
+ } else {
+ MemberUtils.setAccessibleWorkaround(field);
+ }
+ return field.get(target);
+ }
+
+ /**
+ * Read the named public field. Superclasses will be considered.
+ * @param target the object to reflect, must not be null
+ * @param fieldName the field name to obtain
+ * @return the value of the field
+ * @throws IllegalArgumentException if the class or field name is null
+ * @throws IllegalAccessException if the named field is not public
+ */
+ public static Object readField(Object target, String fieldName) throws IllegalAccessException {
+ return readField(target, fieldName, false);
+ }
+
+ /**
+ * Read the named field. Superclasses will be considered.
+ * @param target the object to reflect, must not be null
+ * @param fieldName the field name to obtain
+ * @param forceAccess whether to break scope restrictions using the
+ * setAccessible
method. False
will only
+ * match public fields.
+ * @return the field value
+ * @throws IllegalArgumentException if the class or field name is null
+ * @throws IllegalAccessException if the named field is not made accessible
+ */
+ public static Object readField(Object target, String fieldName, boolean forceAccess) throws IllegalAccessException {
+ if (target == null) {
+ throw new IllegalArgumentException("target object must not be null");
+ }
+ Class cls = target.getClass();
+ Field field = getField(cls, fieldName, forceAccess);
+ if (field == null) {
+ throw new IllegalArgumentException("Cannot locate field " + fieldName + " on " + cls);
+ }
+ //already forced access above, don't repeat it here:
+ return readField(field, target);
+ }
+
+ /**
+ * Read the named public field. Only the class of the specified object will be considered.
+ * @param target the object to reflect, must not be null
+ * @param fieldName the field name to obtain
+ * @return the value of the field
+ * @throws IllegalArgumentException if the class or field name is null
+ * @throws IllegalAccessException if the named field is not public
+ */
+ public static Object readDeclaredField(Object target, String fieldName) throws IllegalAccessException {
+ return readDeclaredField(target, fieldName, false);
+ }
+
+ /**
+ *
Gets a Field value by name. Only the class of the specified
+ * object will be considered.
+ *
+ * @param target the object to reflect, must not be null
+ * @param fieldName the field name to obtain
+ * @param forceAccess whether to break scope restrictions using the
+ * setAccessible
method. False
will only
+ * match public fields.
+ * @return the Field object
+ * @throws IllegalArgumentException if target
or fieldName
is null
+ * @throws IllegalAccessException if the field is not made accessible
+ */
+ public static Object readDeclaredField(Object target, String fieldName, boolean forceAccess) throws IllegalAccessException {
+ if (target == null) {
+ throw new IllegalArgumentException("target object must not be null");
+ }
+ Class cls = target.getClass();
+ Field field = getDeclaredField(cls, fieldName, forceAccess);
+ if (field == null) {
+ throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName);
+ }
+ //already forced access above, don't repeat it here:
+ return readField(field, target);
+ }
+
+ /**
+ * Write a public static Field.
+ * @param field to write
+ * @param value to set
+ * @throws IllegalArgumentException if the field is null or not static
+ * @throws IllegalAccessException if the field is not public or is final
+ */
+ public static void writeStaticField(Field field, Object value) throws IllegalAccessException {
+ writeStaticField(field, value, false);
+ }
+
+ /**
+ * Write a static Field.
+ * @param field to write
+ * @param value to set
+ * @param forceAccess whether to break scope restrictions using the
+ * setAccessible
method. False
will only
+ * match public fields.
+ * @throws IllegalArgumentException if the field is null or not static
+ * @throws IllegalAccessException if the field is not made accessible or is final
+ */
+ public static void writeStaticField(Field field, Object value, boolean forceAccess) throws IllegalAccessException {
+ if (field == null) {
+ throw new IllegalArgumentException("The field must not be null");
+ }
+ if (!Modifier.isStatic(field.getModifiers())) {
+ throw new IllegalArgumentException("The field '" + field.getName() + "' is not static");
+ }
+ writeField(field, (Object) null, value, forceAccess);
+ }
+
+ /**
+ * Write a named public static Field. Superclasses will be considered.
+ * @param cls Class on which the Field is to be found
+ * @param fieldName to write
+ * @param value to set
+ * @throws IllegalArgumentException if the field cannot be located or is not static
+ * @throws IllegalAccessException if the field is not public or is final
+ */
+ public static void writeStaticField(Class cls, String fieldName, Object value) throws IllegalAccessException {
+ writeStaticField(cls, fieldName, value, false);
+ }
+
+ /**
+ * Write a named static Field. Superclasses will be considered.
+ * @param cls Class on which the Field is to be found
+ * @param fieldName to write
+ * @param value to set
+ * @param forceAccess whether to break scope restrictions using the
+ * setAccessible
method. False
will only
+ * match public fields.
+ * @throws IllegalArgumentException if the field cannot be located or is not static
+ * @throws IllegalAccessException if the field is not made accessible or is final
+ */
+ public static void writeStaticField(Class cls, String fieldName, Object value, boolean forceAccess)
+ throws IllegalAccessException {
+ Field field = getField(cls, fieldName, forceAccess);
+ if (field == null) {
+ throw new IllegalArgumentException("Cannot locate field " + fieldName + " on " + cls);
+ }
+ //already forced access above, don't repeat it here:
+ writeStaticField(field, value);
+ }
+
+ /**
+ * Write a named public static Field. Only the specified class will be considered.
+ * @param cls Class on which the Field is to be found
+ * @param fieldName to write
+ * @param value to set
+ * @throws IllegalArgumentException if the field cannot be located or is not static
+ * @throws IllegalAccessException if the field is not public or is final
+ */
+ public static void writeDeclaredStaticField(Class cls, String fieldName, Object value)
+ throws IllegalAccessException {
+ writeDeclaredStaticField(cls, fieldName, value, false);
+ }
+
+ /**
+ * Write a named static Field. Only the specified class will be considered.
+ * @param cls Class on which the Field is to be found
+ * @param fieldName to write
+ * @param value to set
+ * @param forceAccess whether to break scope restrictions using the
+ * setAccessible
method. False
will only
+ * match public fields.
+ * @throws IllegalArgumentException if the field cannot be located or is not static
+ * @throws IllegalAccessException if the field is not made accessible or is final
+ */
+ public static void writeDeclaredStaticField(Class cls, String fieldName, Object value, boolean forceAccess)
+ throws IllegalAccessException {
+ Field field = getDeclaredField(cls, fieldName, forceAccess);
+ if (field == null) {
+ throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName);
+ }
+ //already forced access above, don't repeat it here:
+ writeField(field, (Object) null, value);
+ }
+
+ /**
+ * Write an accessible field.
+ * @param field to write
+ * @param target the object to call on, may be null for static fields
+ * @param value to set
+ * @throws IllegalArgumentException if the field is null
+ * @throws IllegalAccessException if the field is not accessible or is final
+ */
+ public static void writeField(Field field, Object target, Object value) throws IllegalAccessException {
+ writeField(field, target, value, false);
+ }
+
+ /**
+ * Write a field.
+ * @param field to write
+ * @param target the object to call on, may be null for static fields
+ * @param value to set
+ * @param forceAccess whether to break scope restrictions using the
+ * setAccessible
method. False
will only
+ * match public fields.
+ * @throws IllegalArgumentException if the field is null
+ * @throws IllegalAccessException if the field is not made accessible or is final
+ */
+ public static void writeField(Field field, Object target, Object value, boolean forceAccess) throws IllegalAccessException {
+ if (field == null) {
+ throw new IllegalArgumentException("The field must not be null");
+ }
+ if (forceAccess && !field.isAccessible()) {
+ field.setAccessible(true);
+ } else {
+ MemberUtils.setAccessibleWorkaround(field);
+ }
+ field.set(target, value);
+ }
+
+ /**
+ * Write a public field. Superclasses will be considered.
+ * @param target the object to reflect, must not be null
+ * @param fieldName the field name to obtain
+ * @param value to set
+ * @throws IllegalArgumentException if target
or fieldName
is null
+ * @throws IllegalAccessException if the field is not accessible
+ */
+ public static void writeField(Object target, String fieldName, Object value) throws IllegalAccessException {
+ writeField(target, fieldName, value, false);
+ }
+
+ /**
+ * Write a field. Superclasses will be considered.
+ * @param target the object to reflect, must not be null
+ * @param fieldName the field name to obtain
+ * @param value to set
+ * @param forceAccess whether to break scope restrictions using the
+ * setAccessible
method. False
will only
+ * match public fields.
+ * @throws IllegalArgumentException if target
or fieldName
is null
+ * @throws IllegalAccessException if the field is not made accessible
+ */
+ public static void writeField(Object target, String fieldName, Object value, boolean forceAccess)
+ throws IllegalAccessException {
+ if (target == null) {
+ throw new IllegalArgumentException("target object must not be null");
+ }
+ Class cls = target.getClass();
+ Field field = getField(cls, fieldName, forceAccess);
+ if (field == null) {
+ throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName);
+ }
+ //already forced access above, don't repeat it here:
+ writeField(field, target, value);
+ }
+
+ /**
+ * Write a public field. Only the specified class will be considered.
+ * @param target the object to reflect, must not be null
+ * @param fieldName the field name to obtain
+ * @param value to set
+ * @throws IllegalArgumentException if target
or fieldName
is null
+ * @throws IllegalAccessException if the field is not made accessible
+ */
+ public static void writeDeclaredField(Object target, String fieldName, Object value) throws IllegalAccessException {
+ writeDeclaredField(target, fieldName, value, false);
+ }
+
+ /**
+ * Write a public field. Only the specified class will be considered.
+ * @param target the object to reflect, must not be null
+ * @param fieldName the field name to obtain
+ * @param value to set
+ * @param forceAccess whether to break scope restrictions using the
+ * setAccessible
method. False
will only
+ * match public fields.
+ * @throws IllegalArgumentException if target
or fieldName
is null
+ * @throws IllegalAccessException if the field is not made accessible
+ */
+ public static void writeDeclaredField(Object target, String fieldName, Object value, boolean forceAccess)
+ throws IllegalAccessException {
+ if (target == null) {
+ throw new IllegalArgumentException("target object must not be null");
+ }
+ Class cls = target.getClass();
+ Field field = getDeclaredField(cls, fieldName, forceAccess);
+ if (field == null) {
+ throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName);
+ }
+ //already forced access above, don't repeat it here:
+ writeField(field, target, value);
+ }
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/reflect/MemberUtils.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/reflect/MemberUtils.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/reflect/MemberUtils.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,220 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang.reflect;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.ClassUtils;
+import org.apache.commons.lang.SystemUtils;
+
+/**
+ * Contains common code for working with Methods/Constructors, extracted and
+ * refactored from MethodUtils
when it was imported from Commons
+ * BeanUtils.
+ *
+ * @author Apache Software Foundation
+ * @author Steve Cohen
+ * @author Matt Benson
+ * @since 2.5
+ * @version $Id$
+ */
+abstract class MemberUtils {
+ // TODO extract an interface to implement compareParameterSets(...)?
+
+ private static final int ACCESS_TEST = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE;
+
+ private static final Method IS_SYNTHETIC;
+ static {
+ Method isSynthetic = null;
+ if (SystemUtils.isJavaVersionAtLeast(1.5f)) {
+ // cannot call synthetic methods:
+ try {
+ isSynthetic = Member.class.getMethod("isSynthetic",
+ ArrayUtils.EMPTY_CLASS_ARRAY);
+ } catch (Exception e) {
+ }
+ }
+ IS_SYNTHETIC = isSynthetic;
+ }
+
+ /** Array of primitive number types ordered by "promotability" */
+ private static final Class[] ORDERED_PRIMITIVE_TYPES = { Byte.TYPE, Short.TYPE,
+ Character.TYPE, Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE };
+
+ /**
+ * XXX Default access superclass workaround
+ *
+ * When a public class has a default access superclass with public members,
+ * these members are accessible. Calling them from compiled code works fine.
+ * Unfortunately, on some JVMs, using reflection to invoke these members
+ * seems to (wrongly) to prevent access even when the modifer is public.
+ * Calling setAccessible(true) solves the problem but will only work from
+ * sufficiently privileged code. Better workarounds would be gratefully
+ * accepted.
+ * @param o the AccessibleObject to set as accessible
+ */
+ static void setAccessibleWorkaround(AccessibleObject o) {
+ if (o == null || o.isAccessible()) {
+ return;
+ }
+ Member m = (Member) o;
+ if (Modifier.isPublic(m.getModifiers())
+ && isPackageAccess(m.getDeclaringClass().getModifiers())) {
+ try {
+ o.setAccessible(true);
+ } catch (SecurityException e) {
+ // ignore in favor of subsequent IllegalAccessException
+ }
+ }
+ }
+
+ /**
+ * Learn whether a given set of modifiers implies package access.
+ * @param modifiers to test
+ * @return true unless package/protected/private modifier detected
+ */
+ static boolean isPackageAccess(int modifiers) {
+ return (modifiers & ACCESS_TEST) == 0;
+ }
+
+ /**
+ * Check a Member for basic accessibility.
+ * @param m Member to check
+ * @return true if m
is accessible
+ */
+ static boolean isAccessible(Member m) {
+ return m != null && Modifier.isPublic(m.getModifiers()) && !isSynthetic(m);
+ }
+
+ /**
+ * Try to learn whether a given member, on JDK >= 1.5, is synthetic.
+ * @param m Member to check
+ * @return true if m
was introduced by the compiler.
+ */
+ static boolean isSynthetic(Member m) {
+ if (IS_SYNTHETIC != null) {
+ try {
+ return ((Boolean) IS_SYNTHETIC.invoke(m, null)).booleanValue();
+ } catch (Exception e) {
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Compare the relative fitness of two sets of parameter types in terms of
+ * matching a third set of runtime parameter types, such that a list ordered
+ * by the results of the comparison would return the best match first
+ * (least).
+ *
+ * @param left the "left" parameter set
+ * @param right the "right" parameter set
+ * @param actual the runtime parameter types to match against
+ * left
/right
+ * @return int consistent with compare
semantics
+ */
+ static int compareParameterTypes(Class[] left, Class[] right, Class[] actual) {
+ float leftCost = getTotalTransformationCost(actual, left);
+ float rightCost = getTotalTransformationCost(actual, right);
+ return leftCost < rightCost ? -1 : rightCost < leftCost ? 1 : 0;
+ }
+
+ /**
+ * Returns the sum of the object transformation cost for each class in the
+ * source argument list.
+ * @param srcArgs The source arguments
+ * @param destArgs The destination arguments
+ * @return The total transformation cost
+ */
+ private static float getTotalTransformationCost(Class[] srcArgs, Class[] destArgs) {
+ float totalCost = 0.0f;
+ for (int i = 0; i < srcArgs.length; i++) {
+ Class srcClass, destClass;
+ srcClass = srcArgs[i];
+ destClass = destArgs[i];
+ totalCost += getObjectTransformationCost(srcClass, destClass);
+ }
+ return totalCost;
+ }
+
+ /**
+ * Gets the number of steps required needed to turn the source class into
+ * the destination class. This represents the number of steps in the object
+ * hierarchy graph.
+ * @param srcClass The source class
+ * @param destClass The destination class
+ * @return The cost of transforming an object
+ */
+ private static float getObjectTransformationCost(Class srcClass, Class destClass) {
+ if (destClass.isPrimitive()) {
+ return getPrimitivePromotionCost(srcClass, destClass);
+ }
+ float cost = 0.0f;
+ while (srcClass != null && !destClass.equals(srcClass)) {
+ if (destClass.isInterface() && ClassUtils.isAssignable(srcClass, destClass)) {
+ // slight penalty for interface match.
+ // we still want an exact match to override an interface match,
+ // but
+ // an interface match should override anything where we have to
+ // get a superclass.
+ cost += 0.25f;
+ break;
+ }
+ cost++;
+ srcClass = srcClass.getSuperclass();
+ }
+ /*
+ * If the destination class is null, we've travelled all the way up to
+ * an Object match. We'll penalize this by adding 1.5 to the cost.
+ */
+ if (srcClass == null) {
+ cost += 1.5f;
+ }
+ return cost;
+ }
+
+ /**
+ * Get the number of steps required to promote a primitive number to another
+ * type.
+ * @param srcClass the (primitive) source class
+ * @param destClass the (primitive) destination class
+ * @return The cost of promoting the primitive
+ */
+ private static float getPrimitivePromotionCost(final Class srcClass, final Class destClass) {
+ float cost = 0.0f;
+ Class cls = srcClass;
+ if (!cls.isPrimitive()) {
+ // slight unwrapping penalty
+ cost += 0.1f;
+ cls = ClassUtils.wrapperToPrimitive(cls);
+ }
+ for (int i = 0; cls != destClass && i < ORDERED_PRIMITIVE_TYPES.length; i++) {
+ if (cls == ORDERED_PRIMITIVE_TYPES[i]) {
+ cost += 0.1f;
+ if (i < ORDERED_PRIMITIVE_TYPES.length - 1) {
+ cls = ORDERED_PRIMITIVE_TYPES[i + 1];
+ }
+ }
+ }
+ return cost;
+ }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/reflect/MethodUtils.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/reflect/MethodUtils.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/reflect/MethodUtils.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,678 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang.reflect;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.ClassUtils;
+
+/**
+ *
Utility reflection methods focused on methods, originally from Commons BeanUtils.
+ * Differences from the BeanUtils version may be noted, especially where similar functionality
+ * already existed within Lang.
+ *
+ *
+ * Known Limitations
+ * Accessing Public Methods In A Default Access Superclass
+ * There is an issue when invoking public methods contained in a default access superclass on JREs prior to 1.4.
+ * Reflection locates these methods fine and correctly assigns them as public.
+ * However, an IllegalAccessException
is thrown if the method is invoked.
+ *
+ * MethodUtils
contains a workaround for this situation.
+ * It will attempt to call setAccessible
on this method.
+ * If this call succeeds, then the method can be invoked as normal.
+ * This call will only succeed when the application has sufficient security privileges.
+ * If this call fails then the method may fail.
+ *
+ * @author Apache Software Foundation
+ * @author Craig R. McClanahan
+ * @author Ralph Schaer
+ * @author Chris Audley
+ * @author Rey François
+ * @author Gregor Raýman
+ * @author Jan Sorensen
+ * @author Robert Burrell Donkin
+ * @author Matt Benson
+ * @since 2.5
+ * @version $Id$
+ */
+public class MethodUtils {
+
+ /**
+ * MethodUtils instances should NOT be constructed in standard programming.
+ * Instead, the class should be used as
+ * MethodUtils.getAccessibleMethod(method)
.
+ *
+ * This constructor is public to permit tools that require a JavaBean
+ * instance to operate.
+ */
+ public MethodUtils() {
+ super();
+ }
+
+ /**
+ * Invoke a named method whose parameter type matches the object type.
+ *
+ * This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.
+ *
+ * This method supports calls to methods taking primitive parameters
+ * via passing in wrapping classes. So, for example, a Boolean
object
+ * would match a boolean
primitive.
+ *
+ * This is a convenient wrapper for
+ * {@link #invokeMethod(Object object, String methodName, Object[] args)}.
+ *
+ *
+ * @param object invoke method on this object
+ * @param methodName get method with this name
+ * @param arg use this argument
+ * @return The value returned by the invoked method
+ *
+ * @throws NoSuchMethodException if there is no such accessible method
+ * @throws InvocationTargetException wraps an exception thrown by the method invoked
+ * @throws IllegalAccessException if the requested method is not accessible via reflection
+ */
+ public static Object invokeMethod(Object object, String methodName,
+ Object arg) throws NoSuchMethodException, IllegalAccessException,
+ InvocationTargetException {
+ return invokeMethod(object, methodName, new Object[] { arg });
+ }
+
+ /**
+ * Invoke a named method whose parameter type matches the object type.
+ *
+ * This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.
+ *
+ * This method supports calls to methods taking primitive parameters
+ * via passing in wrapping classes. So, for example, a Boolean
object
+ * would match a boolean
primitive.
+ *
+ * This is a convenient wrapper for
+ * {@link #invokeMethod(Object object,String methodName, Object[] args, Class[] parameterTypes)}.
+ *
+ *
+ * @param object invoke method on this object
+ * @param methodName get method with this name
+ * @param args use these arguments - treat null as empty array
+ * @return The value returned by the invoked method
+ *
+ * @throws NoSuchMethodException if there is no such accessible method
+ * @throws InvocationTargetException wraps an exception thrown by the method invoked
+ * @throws IllegalAccessException if the requested method is not accessible via reflection
+ */
+ public static Object invokeMethod(Object object, String methodName,
+ Object[] args) throws NoSuchMethodException,
+ IllegalAccessException, InvocationTargetException {
+ if (args == null) {
+ args = ArrayUtils.EMPTY_OBJECT_ARRAY;
+ }
+ int arguments = args.length;
+ Class[] parameterTypes = new Class[arguments];
+ for (int i = 0; i < arguments; i++) {
+ parameterTypes[i] = args[i].getClass();
+ }
+ return invokeMethod(object, methodName, args, parameterTypes);
+ }
+
+ /**
+ * Invoke a named method whose parameter type matches the object type.
+ *
+ * This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.
+ *
+ * This method supports calls to methods taking primitive parameters
+ * via passing in wrapping classes. So, for example, a Boolean
object
+ * would match a boolean
primitive.
+ *
+ * @param object invoke method on this object
+ * @param methodName get method with this name
+ * @param args use these arguments - treat null as empty array
+ * @param parameterTypes match these parameters - treat null as empty array
+ * @return The value returned by the invoked method
+ *
+ * @throws NoSuchMethodException if there is no such accessible method
+ * @throws InvocationTargetException wraps an exception thrown by the method invoked
+ * @throws IllegalAccessException if the requested method is not accessible via reflection
+ */
+ public static Object invokeMethod(Object object, String methodName,
+ Object[] args, Class[] parameterTypes)
+ throws NoSuchMethodException, IllegalAccessException,
+ InvocationTargetException {
+ if (parameterTypes == null) {
+ parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
+ }
+ if (args == null) {
+ args = ArrayUtils.EMPTY_OBJECT_ARRAY;
+ }
+ Method method = getMatchingAccessibleMethod(object.getClass(),
+ methodName, parameterTypes);
+ if (method == null) {
+ throw new NoSuchMethodException("No such accessible method: "
+ + methodName + "() on object: "
+ + object.getClass().getName());
+ }
+ return method.invoke(object, args);
+ }
+
+ /**
+ * Invoke a method whose parameter type matches exactly the object
+ * type.
+ *
+ * This is a convenient wrapper for
+ * {@link #invokeExactMethod(Object object,String methodName,Object [] args)}.
+ *
+ *
+ * @param object invoke method on this object
+ * @param methodName get method with this name
+ * @param arg use this argument
+ * @return The value returned by the invoked method
+ *
+ * @throws NoSuchMethodException if there is no such accessible method
+ * @throws InvocationTargetException wraps an exception thrown by the
+ * method invoked
+ * @throws IllegalAccessException if the requested method is not accessible
+ * via reflection
+ */
+ public static Object invokeExactMethod(Object object, String methodName,
+ Object arg) throws NoSuchMethodException, IllegalAccessException,
+ InvocationTargetException {
+ return invokeExactMethod(object, methodName, new Object[] { arg });
+ }
+
+ /**
+ * Invoke a method whose parameter types match exactly the object
+ * types.
+ *
+ * This uses reflection to invoke the method obtained from a call to
+ * getAccessibleMethod()
.
+ *
+ * @param object invoke method on this object
+ * @param methodName get method with this name
+ * @param args use these arguments - treat null as empty array
+ * @return The value returned by the invoked method
+ *
+ * @throws NoSuchMethodException if there is no such accessible method
+ * @throws InvocationTargetException wraps an exception thrown by the
+ * method invoked
+ * @throws IllegalAccessException if the requested method is not accessible
+ * via reflection
+ */
+ public static Object invokeExactMethod(Object object, String methodName,
+ Object[] args) throws NoSuchMethodException,
+ IllegalAccessException, InvocationTargetException {
+ if (args == null) {
+ args = ArrayUtils.EMPTY_OBJECT_ARRAY;
+ }
+ int arguments = args.length;
+ Class[] parameterTypes = new Class[arguments];
+ for (int i = 0; i < arguments; i++) {
+ parameterTypes[i] = args[i].getClass();
+ }
+ return invokeExactMethod(object, methodName, args, parameterTypes);
+ }
+
+ /**
+ * Invoke a method whose parameter types match exactly the parameter
+ * types given.
+ *
+ * This uses reflection to invoke the method obtained from a call to
+ * getAccessibleMethod()
.
+ *
+ * @param object invoke method on this object
+ * @param methodName get method with this name
+ * @param args use these arguments - treat null as empty array
+ * @param parameterTypes match these parameters - treat null as empty array
+ * @return The value returned by the invoked method
+ *
+ * @throws NoSuchMethodException if there is no such accessible method
+ * @throws InvocationTargetException wraps an exception thrown by the
+ * method invoked
+ * @throws IllegalAccessException if the requested method is not accessible
+ * via reflection
+ */
+ public static Object invokeExactMethod(Object object, String methodName,
+ Object[] args, Class[] parameterTypes)
+ throws NoSuchMethodException, IllegalAccessException,
+ InvocationTargetException {
+ if (args == null) {
+ args = ArrayUtils.EMPTY_OBJECT_ARRAY;
+ }
+ if (parameterTypes == null) {
+ parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
+ }
+ Method method = getAccessibleMethod(object.getClass(), methodName,
+ parameterTypes);
+ if (method == null) {
+ throw new NoSuchMethodException("No such accessible method: "
+ + methodName + "() on object: "
+ + object.getClass().getName());
+ }
+ return method.invoke(object, args);
+ }
+
+ /**
+ * Invoke a static method whose parameter types match exactly the parameter
+ * types given.
+ *
+ * This uses reflection to invoke the method obtained from a call to
+ * {@link #getAccessibleMethod(Class, String, Class[])}.
+ *
+ * @param cls invoke static method on this class
+ * @param methodName get method with this name
+ * @param args use these arguments - treat null as empty array
+ * @param parameterTypes match these parameters - treat null as empty array
+ * @return The value returned by the invoked method
+ *
+ * @throws NoSuchMethodException if there is no such accessible method
+ * @throws InvocationTargetException wraps an exception thrown by the
+ * method invoked
+ * @throws IllegalAccessException if the requested method is not accessible
+ * via reflection
+ */
+ public static Object invokeExactStaticMethod(Class cls, String methodName,
+ Object[] args, Class[] parameterTypes)
+ throws NoSuchMethodException, IllegalAccessException,
+ InvocationTargetException {
+ if (args == null) {
+ args = ArrayUtils.EMPTY_OBJECT_ARRAY;
+ }
+ if (parameterTypes == null) {
+ parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
+ }
+ Method method = getAccessibleMethod(cls, methodName, parameterTypes);
+ if (method == null) {
+ throw new NoSuchMethodException("No such accessible method: "
+ + methodName + "() on class: " + cls.getName());
+ }
+ return method.invoke(null, args);
+ }
+
+ /**
+ * Invoke a named static method whose parameter type matches the object type.
+ *
+ * This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.
+ *
+ * This method supports calls to methods taking primitive parameters
+ * via passing in wrapping classes. So, for example, a Boolean
class
+ * would match a boolean
primitive.
+ *
+ * This is a convenient wrapper for
+ * {@link #invokeStaticMethod(Class objectClass,String methodName,Object [] args)}.
+ *
+ *
+ * @param cls invoke static method on this class
+ * @param methodName get method with this name
+ * @param arg use this argument
+ * @return The value returned by the invoked method
+ *
+ * @throws NoSuchMethodException if there is no such accessible method
+ * @throws InvocationTargetException wraps an exception thrown by the
+ * method invoked
+ * @throws IllegalAccessException if the requested method is not accessible
+ * via reflection
+ */
+ public static Object invokeStaticMethod(Class cls, String methodName,
+ Object arg) throws NoSuchMethodException, IllegalAccessException,
+ InvocationTargetException {
+ return invokeStaticMethod(cls, methodName, new Object[] { arg });
+ }
+
+ /**
+ * Invoke a named static method whose parameter type matches the object type.
+ *
+ * This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.
+ *
+ * This method supports calls to methods taking primitive parameters
+ * via passing in wrapping classes. So, for example, a Boolean
class
+ * would match a boolean
primitive.
+ *
+ * This is a convenient wrapper for
+ * {@link #invokeStaticMethod(Class objectClass,String methodName,Object [] args,Class[] parameterTypes)}.
+ *
+ *
+ * @param cls invoke static method on this class
+ * @param methodName get method with this name
+ * @param args use these arguments - treat null as empty array
+ * @return The value returned by the invoked method
+ *
+ * @throws NoSuchMethodException if there is no such accessible method
+ * @throws InvocationTargetException wraps an exception thrown by the
+ * method invoked
+ * @throws IllegalAccessException if the requested method is not accessible
+ * via reflection
+ */
+ public static Object invokeStaticMethod(Class cls, String methodName,
+ Object[] args) throws NoSuchMethodException,
+ IllegalAccessException, InvocationTargetException {
+ if (args == null) {
+ args = ArrayUtils.EMPTY_OBJECT_ARRAY;
+ }
+ int arguments = args.length;
+ Class[] parameterTypes = new Class[arguments];
+ for (int i = 0; i < arguments; i++) {
+ parameterTypes[i] = args[i].getClass();
+ }
+ return invokeStaticMethod(cls, methodName, args, parameterTypes);
+ }
+
+ /**
+ * Invoke a named static method whose parameter type matches the object type.
+ *
+ * This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.
+ *
+ * This method supports calls to methods taking primitive parameters
+ * via passing in wrapping classes. So, for example, a Boolean
class
+ * would match a boolean
primitive.
+ *
+ *
+ * @param cls invoke static method on this class
+ * @param methodName get method with this name
+ * @param args use these arguments - treat null as empty array
+ * @param parameterTypes match these parameters - treat null as empty array
+ * @return The value returned by the invoked method
+ *
+ * @throws NoSuchMethodException if there is no such accessible method
+ * @throws InvocationTargetException wraps an exception thrown by the
+ * method invoked
+ * @throws IllegalAccessException if the requested method is not accessible
+ * via reflection
+ */
+ public static Object invokeStaticMethod(Class cls, String methodName,
+ Object[] args, Class[] parameterTypes)
+ throws NoSuchMethodException, IllegalAccessException,
+ InvocationTargetException {
+ if (parameterTypes == null) {
+ parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
+ }
+ if (args == null) {
+ args = ArrayUtils.EMPTY_OBJECT_ARRAY;
+ }
+ Method method = getMatchingAccessibleMethod(cls, methodName,
+ parameterTypes);
+ if (method == null) {
+ throw new NoSuchMethodException("No such accessible method: "
+ + methodName + "() on class: " + cls.getName());
+ }
+ return method.invoke(null, args);
+ }
+
+ /**
+ * Invoke a static method whose parameter type matches exactly the object
+ * type.
+ *
+ * This is a convenient wrapper for
+ * {@link #invokeExactStaticMethod(Class objectClass,String methodName,Object [] args)}.
+ *
+ *
+ * @param cls invoke static method on this class
+ * @param methodName get method with this name
+ * @param arg use this argument
+ * @return The value returned by the invoked method
+ *
+ * @throws NoSuchMethodException if there is no such accessible method
+ * @throws InvocationTargetException wraps an exception thrown by the
+ * method invoked
+ * @throws IllegalAccessException if the requested method is not accessible
+ * via reflection
+ */
+ public static Object invokeExactStaticMethod(Class cls, String methodName,
+ Object arg) throws NoSuchMethodException, IllegalAccessException,
+ InvocationTargetException {
+ return invokeExactStaticMethod(cls, methodName, new Object[] { arg });
+ }
+
+ /**
+ * Invoke a static method whose parameter types match exactly the object
+ * types.
+ *
+ * This uses reflection to invoke the method obtained from a call to
+ * {@link #getAccessibleMethod(Class, String, Class[])}.
+ *
+ * @param cls invoke static method on this class
+ * @param methodName get method with this name
+ * @param args use these arguments - treat null as empty array
+ * @return The value returned by the invoked method
+ *
+ * @throws NoSuchMethodException if there is no such accessible method
+ * @throws InvocationTargetException wraps an exception thrown by the
+ * method invoked
+ * @throws IllegalAccessException if the requested method is not accessible
+ * via reflection
+ */
+ public static Object invokeExactStaticMethod(Class cls, String methodName,
+ Object[] args) throws NoSuchMethodException,
+ IllegalAccessException, InvocationTargetException {
+ if (args == null) {
+ args = ArrayUtils.EMPTY_OBJECT_ARRAY;
+ }
+ int arguments = args.length;
+ Class[] parameterTypes = new Class[arguments];
+ for (int i = 0; i < arguments; i++) {
+ parameterTypes[i] = args[i].getClass();
+ }
+ return invokeExactStaticMethod(cls, methodName, args, parameterTypes);
+ }
+
+ /**
+ * Return an accessible method (that is, one that can be invoked via
+ * reflection) with given name and a single parameter. If no such method
+ * can be found, return null
.
+ * Basically, a convenience wrapper that constructs a Class
+ * array for you.
+ *
+ * @param cls get method from this class
+ * @param methodName get method with this name
+ * @param parameterType taking this type of parameter
+ * @return The accessible method
+ */
+ public static Method getAccessibleMethod(Class cls, String methodName,
+ Class parameterType) {
+ return getAccessibleMethod(cls, methodName,
+ new Class[] { parameterType });
+ }
+
+ /**
+ * Return an accessible method (that is, one that can be invoked via
+ * reflection) with given name and parameters. If no such method
+ * can be found, return null
.
+ * This is just a convenient wrapper for
+ * {@link #getAccessibleMethod(Method method)}.
+ *
+ * @param cls get method from this class
+ * @param methodName get method with this name
+ * @param parameterTypes with these parameters types
+ * @return The accessible method
+ */
+ public static Method getAccessibleMethod(Class cls, String methodName,
+ Class[] parameterTypes) {
+ try {
+ return getAccessibleMethod(cls.getMethod(methodName,
+ parameterTypes));
+ } catch (NoSuchMethodException e) {
+ return (null);
+ }
+ }
+
+ /**
+ * Return an accessible method (that is, one that can be invoked via
+ * reflection) that implements the specified Method. If no such method
+ * can be found, return null
.
+ *
+ * @param method The method that we wish to call
+ * @return The accessible method
+ */
+ public static Method getAccessibleMethod(Method method) {
+ if (!MemberUtils.isAccessible(method)) {
+ return null;
+ }
+ // If the declaring class is public, we are done
+ Class cls = method.getDeclaringClass();
+ if (Modifier.isPublic(cls.getModifiers())) {
+ return method;
+ }
+ String methodName = method.getName();
+ Class[] parameterTypes = method.getParameterTypes();
+
+ // Check the implemented interfaces and subinterfaces
+ method = getAccessibleMethodFromInterfaceNest(cls, methodName,
+ parameterTypes);
+
+ // Check the superclass chain
+ if (method == null) {
+ method = getAccessibleMethodFromSuperclass(cls, methodName,
+ parameterTypes);
+ }
+ return method;
+ }
+
+ /**
+ * Return an accessible method (that is, one that can be invoked via
+ * reflection) by scanning through the superclasses. If no such method
+ * can be found, return null
.
+ *
+ * @param cls Class to be checked
+ * @param methodName Method name of the method we wish to call
+ * @param parameterTypes The parameter type signatures
+ * @return the accessible method or null
if not found
+ */
+ private static Method getAccessibleMethodFromSuperclass(Class cls,
+ String methodName, Class[] parameterTypes) {
+ Class parentClass = cls.getSuperclass();
+ while (parentClass != null) {
+ if (Modifier.isPublic(parentClass.getModifiers())) {
+ try {
+ return parentClass.getMethod(methodName, parameterTypes);
+ } catch (NoSuchMethodException e) {
+ return null;
+ }
+ }
+ parentClass = parentClass.getSuperclass();
+ }
+ return null;
+ }
+
+ /**
+ * Return an accessible method (that is, one that can be invoked via
+ * reflection) that implements the specified method, by scanning through
+ * all implemented interfaces and subinterfaces. If no such method
+ * can be found, return null
.
+ *
+ * There isn't any good reason why this method must be private.
+ * It is because there doesn't seem any reason why other classes should
+ * call this rather than the higher level methods.
+ *
+ * @param cls Parent class for the interfaces to be checked
+ * @param methodName Method name of the method we wish to call
+ * @param parameterTypes The parameter type signatures
+ * @return the accessible method or null
if not found
+ */
+ private static Method getAccessibleMethodFromInterfaceNest(Class cls,
+ String methodName, Class[] parameterTypes) {
+ Method method = null;
+
+ // Search up the superclass chain
+ for (; cls != null; cls = cls.getSuperclass()) {
+
+ // Check the implemented interfaces of the parent class
+ Class[] interfaces = cls.getInterfaces();
+ for (int i = 0; i < interfaces.length; i++) {
+ // Is this interface public?
+ if (!Modifier.isPublic(interfaces[i].getModifiers())) {
+ continue;
+ }
+ // Does the method exist on this interface?
+ try {
+ method = interfaces[i].getDeclaredMethod(methodName,
+ parameterTypes);
+ } catch (NoSuchMethodException e) {
+ /*
+ * Swallow, if no method is found after the loop then this
+ * method returns null.
+ */
+ }
+ if (method != null) {
+ break;
+ }
+ // Recursively check our parent interfaces
+ method = getAccessibleMethodFromInterfaceNest(interfaces[i],
+ methodName, parameterTypes);
+ if (method != null) {
+ break;
+ }
+ }
+ }
+ return method;
+ }
+
+ /**
+ * Find an accessible method that matches the given name and has compatible parameters.
+ * Compatible parameters mean that every method parameter is assignable from
+ * the given parameters.
+ * In other words, it finds a method with the given name
+ * that will take the parameters given.
+ *
+ *
This method is used by
+ * {@link
+ * #invokeMethod(Object object, String methodName, Object[] args, Class[] parameterTypes)}.
+ *
+ *
This method can match primitive parameter by passing in wrapper classes.
+ * For example, a Boolean
will match a primitive boolean
+ * parameter.
+ *
+ * @param cls find method in this class
+ * @param methodName find method with this name
+ * @param parameterTypes find method with most compatible parameters
+ * @return The accessible method
+ */
+ public static Method getMatchingAccessibleMethod(Class cls,
+ String methodName, Class[] parameterTypes) {
+ try {
+ Method method = cls.getMethod(methodName, parameterTypes);
+ MemberUtils.setAccessibleWorkaround(method);
+ return method;
+ } catch (NoSuchMethodException e) { /* SWALLOW */
+ }
+ // search through all methods
+ Method bestMatch = null;
+ Method[] methods = cls.getMethods();
+ for (int i = 0, size = methods.length; i < size; i++) {
+ if (methods[i].getName().equals(methodName)) {
+ // compare parameters
+ if (ClassUtils.isAssignable(parameterTypes, methods[i]
+ .getParameterTypes(), true)) {
+ // get accessible version of method
+ Method accessibleMethod = getAccessibleMethod(methods[i]);
+ if (accessibleMethod != null) {
+ if (bestMatch == null
+ || MemberUtils.compareParameterTypes(
+ accessibleMethod.getParameterTypes(),
+ bestMatch.getParameterTypes(),
+ parameterTypes) < 0) {
+ bestMatch = accessibleMethod;
+ }
+ }
+ }
+ }
+ }
+ if (bestMatch != null) {
+ MemberUtils.setAccessibleWorkaround(bestMatch);
+ }
+ return bestMatch;
+ }
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/reflect/package.html
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/reflect/package.html (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/reflect/package.html (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+Accumulates common high-level uses of the java.lang.reflect
APIs.
+@since 2.5
+These classes are immutable, and therefore thread-safe.
+
+
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/text/CompositeFormat.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/text/CompositeFormat.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/text/CompositeFormat.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang.text;
+
+import java.text.FieldPosition;
+import java.text.Format;
+import java.text.ParseException;
+import java.text.ParsePosition;
+
+/**
+ * Formats using one formatter and parses using a different formatter. An
+ * example of use for this would be a webapp where data is taken in one way and
+ * stored in a database another way.
+ *
+ * @author Apache Software Foundation
+ * @author Archimedes Trajano
+ * @version $Id$
+ */
+public class CompositeFormat extends Format {
+
+ /**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = -4329119827877627683L;
+
+ /** The parser to use. */
+ private final Format parser;
+ /** The formatter to use. */
+ private final Format formatter;
+
+ /**
+ * Create a format that points its parseObject method to one implementation
+ * and its format method to another.
+ *
+ * @param parser implementation
+ * @param formatter implementation
+ */
+ public CompositeFormat(Format parser, Format formatter) {
+ this.parser = parser;
+ this.formatter = formatter;
+ }
+
+ /**
+ * Uses the formatter Format instance.
+ *
+ * @param obj the object to format
+ * @param toAppendTo the {@link StringBuffer} to append to
+ * @param pos the FieldPosition to use (or ignore).
+ * @return toAppendTo
+ * @see Format#format(Object, StringBuffer, FieldPosition)
+ */
+ public StringBuffer format(Object obj, StringBuffer toAppendTo,
+ FieldPosition pos) {
+ return formatter.format(obj, toAppendTo, pos);
+ }
+
+ /**
+ * Uses the parser Format instance.
+ *
+ * @param source the String source
+ * @param pos the ParsePosition containing the position to parse from, will
+ * be updated according to parsing success (index) or failure
+ * (error index)
+ * @return the parsed Object
+ * @see Format#parseObject(String, ParsePosition)
+ */
+ public Object parseObject(String source, ParsePosition pos) {
+ return parser.parseObject(source, pos);
+ }
+
+ /**
+ * Provides access to the parser Format implementation.
+ *
+ * @return parser Format implementation
+ */
+ public Format getParser() {
+ return this.parser;
+ }
+
+ /**
+ * Provides access to the parser Format implementation.
+ *
+ * @return formatter Format implementation
+ */
+ public Format getFormatter() {
+ return this.formatter;
+ }
+
+ /**
+ * Utility method to parse and then reformat a String.
+ *
+ * @param input String to reformat
+ * @return A reformatted String
+ * @throws ParseException thrown by parseObject(String) call
+ */
+ public String reformat(String input) throws ParseException {
+ return format(parseObject(input));
+ }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/text/ExtendedMessageFormat.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/text/ExtendedMessageFormat.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/text/ExtendedMessageFormat.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,530 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang.text;
+
+import java.text.Format;
+import java.text.MessageFormat;
+import java.text.ParsePosition;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.commons.lang.ObjectUtils;
+import org.apache.commons.lang.Validate;
+
+/**
+ * Extends java.text.MessageFormat
to allow pluggable/additional formatting
+ * options for embedded format elements. Client code should specify a registry
+ * of FormatFactory
instances associated with String
+ * format names. This registry will be consulted when the format elements are
+ * parsed from the message pattern. In this way custom patterns can be specified,
+ * and the formats supported by java.text.MessageFormat
can be overridden
+ * at the format and/or format style level (see MessageFormat). A "format element"
+ * embedded in the message pattern is specified (()? signifies optionality):
+ * {
argument-number(,
format-name(,
format-style)?)?}
+ *
+ *
+ * format-name and format-style values are trimmed of surrounding whitespace
+ * in the manner of java.text.MessageFormat
. If format-name denotes
+ * FormatFactory formatFactoryInstance
in registry
, a Format
+ * matching format-name and format-style is requested from
+ * formatFactoryInstance
. If this is successful, the Format
+ * found is used for this format element.
+ *
+ *
+ * NOTICE:: The various subformat mutator methods are considered unnecessary; they exist on the parent
+ * class to allow the type of customization which it is the job of this class to provide in
+ * a configurable fashion. These methods have thus been disabled and will throw
+ * UnsupportedOperationException
if called.
+ *
+ *
+ * Limitations inherited from java.text.MessageFormat
:
+ *
+ * - When using "choice" subformats, support for nested formatting instructions is limited
+ * to that provided by the base class.
+ * - Thread-safety of
Format
s, including MessageFormat
and thus
+ * ExtendedMessageFormat
, is not guaranteed.
+ *
+ *
+ *
+ * @author Apache Software Foundation
+ * @author Matt Benson
+ * @since 2.4
+ * @version $Id$
+ */
+public class ExtendedMessageFormat extends MessageFormat {
+ private static final long serialVersionUID = -2362048321261811743L;
+ private static final int HASH_SEED = 31;
+
+ private static final String DUMMY_PATTERN = "";
+ private static final String ESCAPED_QUOTE = "''";
+ private static final char START_FMT = ',';
+ private static final char END_FE = '}';
+ private static final char START_FE = '{';
+ private static final char QUOTE = '\'';
+
+ private String toPattern;
+ private final Map registry;
+
+ /**
+ * Create a new ExtendedMessageFormat for the default locale.
+ *
+ * @param pattern the pattern to use, not null
+ * @throws IllegalArgumentException in case of a bad pattern.
+ */
+ public ExtendedMessageFormat(String pattern) {
+ this(pattern, Locale.getDefault());
+ }
+
+ /**
+ * Create a new ExtendedMessageFormat.
+ *
+ * @param pattern the pattern to use, not null
+ * @param locale the locale to use, not null
+ * @throws IllegalArgumentException in case of a bad pattern.
+ */
+ public ExtendedMessageFormat(String pattern, Locale locale) {
+ this(pattern, locale, null);
+ }
+
+ /**
+ * Create a new ExtendedMessageFormat for the default locale.
+ *
+ * @param pattern the pattern to use, not null
+ * @param registry the registry of format factories, may be null
+ * @throws IllegalArgumentException in case of a bad pattern.
+ */
+ public ExtendedMessageFormat(String pattern, Map registry) {
+ this(pattern, Locale.getDefault(), registry);
+ }
+
+ /**
+ * Create a new ExtendedMessageFormat.
+ *
+ * @param pattern the pattern to use, not null
+ * @param locale the locale to use, not null
+ * @param registry the registry of format factories, may be null
+ * @throws IllegalArgumentException in case of a bad pattern.
+ */
+ public ExtendedMessageFormat(String pattern, Locale locale, Map registry) {
+ super(DUMMY_PATTERN);
+ setLocale(locale);
+ this.registry = registry;
+ applyPattern(pattern);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toPattern() {
+ return toPattern;
+ }
+
+ /**
+ * Apply the specified pattern.
+ *
+ * @param pattern String
+ */
+ public final void applyPattern(String pattern) {
+ if (registry == null) {
+ super.applyPattern(pattern);
+ toPattern = super.toPattern();
+ return;
+ }
+ ArrayList foundFormats = new ArrayList();
+ ArrayList foundDescriptions = new ArrayList();
+ StrBuilder stripCustom = new StrBuilder(pattern.length());
+
+ ParsePosition pos = new ParsePosition(0);
+ char[] c = pattern.toCharArray();
+ int fmtCount = 0;
+ while (pos.getIndex() < pattern.length()) {
+ switch (c[pos.getIndex()]) {
+ case QUOTE:
+ appendQuotedString(pattern, pos, stripCustom, true);
+ break;
+ case START_FE:
+ fmtCount++;
+ seekNonWs(pattern, pos);
+ int start = pos.getIndex();
+ int index = readArgumentIndex(pattern, next(pos));
+ stripCustom.append(START_FE).append(index);
+ seekNonWs(pattern, pos);
+ Format format = null;
+ String formatDescription = null;
+ if (c[pos.getIndex()] == START_FMT) {
+ formatDescription = parseFormatDescription(pattern,
+ next(pos));
+ format = getFormat(formatDescription);
+ if (format == null) {
+ stripCustom.append(START_FMT).append(formatDescription);
+ }
+ }
+ foundFormats.add(format);
+ foundDescriptions.add(format == null ? null : formatDescription);
+ Validate.isTrue(foundFormats.size() == fmtCount);
+ Validate.isTrue(foundDescriptions.size() == fmtCount);
+ if (c[pos.getIndex()] != END_FE) {
+ throw new IllegalArgumentException(
+ "Unreadable format element at position " + start);
+ }
+ //$FALL-THROUGH$
+ default:
+ stripCustom.append(c[pos.getIndex()]);
+ next(pos);
+ }
+ }
+ super.applyPattern(stripCustom.toString());
+ toPattern = insertFormats(super.toPattern(), foundDescriptions);
+ if (containsElements(foundFormats)) {
+ Format[] origFormats = getFormats();
+ // only loop over what we know we have, as MessageFormat on Java 1.3
+ // seems to provide an extra format element:
+ int i = 0;
+ for (Iterator it = foundFormats.iterator(); it.hasNext(); i++) {
+ Format f = (Format) it.next();
+ if (f != null) {
+ origFormats[i] = f;
+ }
+ }
+ super.setFormats(origFormats);
+ }
+ }
+
+ /**
+ * Throws UnsupportedOperationException - see class Javadoc for details.
+ *
+ * @param formatElementIndex format element index
+ * @param newFormat the new format
+ * @throws UnsupportedOperationException
+ */
+ public void setFormat(int formatElementIndex, Format newFormat) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Throws UnsupportedOperationException - see class Javadoc for details.
+ *
+ * @param argumentIndex argument index
+ * @param newFormat the new format
+ * @throws UnsupportedOperationException
+ */
+ public void setFormatByArgumentIndex(int argumentIndex, Format newFormat) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Throws UnsupportedOperationException - see class Javadoc for details.
+ *
+ * @param newFormats new formats
+ * @throws UnsupportedOperationException
+ */
+ public void setFormats(Format[] newFormats) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Throws UnsupportedOperationException - see class Javadoc for details.
+ *
+ * @param newFormats new formats
+ * @throws UnsupportedOperationException
+ */
+ public void setFormatsByArgumentIndex(Format[] newFormats) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Check if this extended message format is equal to another object.
+ *
+ * @param obj the object to compare to
+ * @return true if this object equals the other, otherwise false
+ * @since 2.6
+ */
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (ObjectUtils.notEqual(getClass(), obj.getClass())) {
+ return false;
+ }
+ ExtendedMessageFormat rhs = (ExtendedMessageFormat)obj;
+ if (ObjectUtils.notEqual(toPattern, rhs.toPattern)) {
+ return false;
+ }
+ if (ObjectUtils.notEqual(registry, rhs.registry)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Return the hashcode.
+ *
+ * @return the hashcode
+ * @since 2.6
+ */
+ public int hashCode() {
+ int result = super.hashCode();
+ result = HASH_SEED * result + ObjectUtils.hashCode(registry);
+ result = HASH_SEED * result + ObjectUtils.hashCode(toPattern);
+ return result;
+ }
+
+ /**
+ * Get a custom format from a format description.
+ *
+ * @param desc String
+ * @return Format
+ */
+ private Format getFormat(String desc) {
+ if (registry != null) {
+ String name = desc;
+ String args = null;
+ int i = desc.indexOf(START_FMT);
+ if (i > 0) {
+ name = desc.substring(0, i).trim();
+ args = desc.substring(i + 1).trim();
+ }
+ FormatFactory factory = (FormatFactory) registry.get(name);
+ if (factory != null) {
+ return factory.getFormat(name, args, getLocale());
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Read the argument index from the current format element
+ *
+ * @param pattern pattern to parse
+ * @param pos current parse position
+ * @return argument index
+ */
+ private int readArgumentIndex(String pattern, ParsePosition pos) {
+ int start = pos.getIndex();
+ seekNonWs(pattern, pos);
+ StrBuilder result = new StrBuilder();
+ boolean error = false;
+ for (; !error && pos.getIndex() < pattern.length(); next(pos)) {
+ char c = pattern.charAt(pos.getIndex());
+ if (Character.isWhitespace(c)) {
+ seekNonWs(pattern, pos);
+ c = pattern.charAt(pos.getIndex());
+ if (c != START_FMT && c != END_FE) {
+ error = true;
+ continue;
+ }
+ }
+ if ((c == START_FMT || c == END_FE) && result.length() > 0) {
+ try {
+ return Integer.parseInt(result.toString());
+ } catch (NumberFormatException e) {
+ // we've already ensured only digits, so unless something
+ // outlandishly large was specified we should be okay.
+ }
+ }
+ error = !Character.isDigit(c);
+ result.append(c);
+ }
+ if (error) {
+ throw new IllegalArgumentException(
+ "Invalid format argument index at position " + start + ": "
+ + pattern.substring(start, pos.getIndex()));
+ }
+ throw new IllegalArgumentException(
+ "Unterminated format element at position " + start);
+ }
+
+ /**
+ * Parse the format component of a format element.
+ *
+ * @param pattern string to parse
+ * @param pos current parse position
+ * @return Format description String
+ */
+ private String parseFormatDescription(String pattern, ParsePosition pos) {
+ int start = pos.getIndex();
+ seekNonWs(pattern, pos);
+ int text = pos.getIndex();
+ int depth = 1;
+ for (; pos.getIndex() < pattern.length(); next(pos)) {
+ switch (pattern.charAt(pos.getIndex())) {
+ case START_FE:
+ depth++;
+ break;
+ case END_FE:
+ depth--;
+ if (depth == 0) {
+ return pattern.substring(text, pos.getIndex());
+ }
+ break;
+ case QUOTE:
+ getQuotedString(pattern, pos, false);
+ break;
+ }
+ }
+ throw new IllegalArgumentException(
+ "Unterminated format element at position " + start);
+ }
+
+ /**
+ * Insert formats back into the pattern for toPattern() support.
+ *
+ * @param pattern source
+ * @param customPatterns The custom patterns to re-insert, if any
+ * @return full pattern
+ */
+ private String insertFormats(String pattern, ArrayList customPatterns) {
+ if (!containsElements(customPatterns)) {
+ return pattern;
+ }
+ StrBuilder sb = new StrBuilder(pattern.length() * 2);
+ ParsePosition pos = new ParsePosition(0);
+ int fe = -1;
+ int depth = 0;
+ while (pos.getIndex() < pattern.length()) {
+ char c = pattern.charAt(pos.getIndex());
+ switch (c) {
+ case QUOTE:
+ appendQuotedString(pattern, pos, sb, false);
+ break;
+ case START_FE:
+ depth++;
+ if (depth == 1) {
+ fe++;
+ sb.append(START_FE).append(
+ readArgumentIndex(pattern, next(pos)));
+ String customPattern = (String) customPatterns.get(fe);
+ if (customPattern != null) {
+ sb.append(START_FMT).append(customPattern);
+ }
+ }
+ break;
+ case END_FE:
+ depth--;
+ //$FALL-THROUGH$
+ default:
+ sb.append(c);
+ next(pos);
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Consume whitespace from the current parse position.
+ *
+ * @param pattern String to read
+ * @param pos current position
+ */
+ private void seekNonWs(String pattern, ParsePosition pos) {
+ int len = 0;
+ char[] buffer = pattern.toCharArray();
+ do {
+ len = StrMatcher.splitMatcher().isMatch(buffer, pos.getIndex());
+ pos.setIndex(pos.getIndex() + len);
+ } while (len > 0 && pos.getIndex() < pattern.length());
+ }
+
+ /**
+ * Convenience method to advance parse position by 1
+ *
+ * @param pos ParsePosition
+ * @return pos
+ */
+ private ParsePosition next(ParsePosition pos) {
+ pos.setIndex(pos.getIndex() + 1);
+ return pos;
+ }
+
+ /**
+ * Consume a quoted string, adding it to appendTo
if
+ * specified.
+ *
+ * @param pattern pattern to parse
+ * @param pos current parse position
+ * @param appendTo optional StringBuffer to append
+ * @param escapingOn whether to process escaped quotes
+ * @return appendTo
+ */
+ private StrBuilder appendQuotedString(String pattern, ParsePosition pos,
+ StrBuilder appendTo, boolean escapingOn) {
+ int start = pos.getIndex();
+ char[] c = pattern.toCharArray();
+ if (escapingOn && c[start] == QUOTE) {
+ next(pos);
+ return appendTo == null ? null : appendTo.append(QUOTE);
+ }
+ int lastHold = start;
+ for (int i = pos.getIndex(); i < pattern.length(); i++) {
+ if (escapingOn && pattern.substring(i).startsWith(ESCAPED_QUOTE)) {
+ appendTo.append(c, lastHold, pos.getIndex() - lastHold).append(
+ QUOTE);
+ pos.setIndex(i + ESCAPED_QUOTE.length());
+ lastHold = pos.getIndex();
+ continue;
+ }
+ switch (c[pos.getIndex()]) {
+ case QUOTE:
+ next(pos);
+ return appendTo == null ? null : appendTo.append(c, lastHold,
+ pos.getIndex() - lastHold);
+ default:
+ next(pos);
+ }
+ }
+ throw new IllegalArgumentException(
+ "Unterminated quoted string at position " + start);
+ }
+
+ /**
+ * Consume quoted string only
+ *
+ * @param pattern pattern to parse
+ * @param pos current parse position
+ * @param escapingOn whether to process escaped quotes
+ */
+ private void getQuotedString(String pattern, ParsePosition pos,
+ boolean escapingOn) {
+ appendQuotedString(pattern, pos, null, escapingOn);
+ }
+
+ /**
+ * Learn whether the specified Collection contains non-null elements.
+ * @param coll to check
+ * @return true
if some Object was found, false
otherwise.
+ */
+ private boolean containsElements(Collection coll) {
+ if (coll == null || coll.size() == 0) {
+ return false;
+ }
+ for (Iterator iter = coll.iterator(); iter.hasNext();) {
+ if (iter.next() != null) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/text/FormatFactory.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/text/FormatFactory.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/text/FormatFactory.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang.text;
+
+import java.text.Format;
+import java.util.Locale;
+
+/**
+ * Format factory.
+ *
+ * @author Apache Software Foundation
+ * @since 2.4
+ * @version $Id$
+ */
+public interface FormatFactory {
+
+ /**
+ * Create or retrieve a format instance.
+ *
+ * @param name The format type name
+ * @param arguments Arguments used to create the format instance. This allows the
+ * FormatFactory
to implement the "format style"
+ * concept from java.text.MessageFormat
.
+ * @param locale The locale, may be null
+ * @return The format instance
+ */
+ Format getFormat(String name, String arguments, Locale locale);
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/text/StrBuilder.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/text/StrBuilder.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/text/StrBuilder.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,2794 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang.text;
+
+import java.io.Reader;
+import java.io.Writer;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.SystemUtils;
+
+/**
+ * Builds a string from constituent parts providing a more flexible and powerful API
+ * than StringBuffer.
+ *
+ * The main differences from StringBuffer/StringBuilder are:
+ *
+ * - Not synchronized
+ * - Not final
+ * - Subclasses have direct access to character array
+ * - Additional methods
+ *
+ * - appendWithSeparators - adds an array of values, with a separator
+ * - appendPadding - adds a length padding characters
+ * - appendFixedLength - adds a fixed width field to the builder
+ * - toCharArray/getChars - simpler ways to get a range of the character array
+ * - delete - delete char or string
+ * - replace - search and replace for a char or string
+ * - leftString/rightString/midString - substring without exceptions
+ * - contains - whether the builder contains a char or string
+ * - size/clear/isEmpty - collections style API methods
+ *
+ *
+ *
+ * - Views
+ *
+ * - asTokenizer - uses the internal buffer as the source of a StrTokenizer
+ * - asReader - uses the internal buffer as the source of a Reader
+ * - asWriter - allows a Writer to write directly to the internal buffer
+ *
+ *
+ *
+ *
+ * The aim has been to provide an API that mimics very closely what StringBuffer
+ * provides, but with additional methods. It should be noted that some edge cases,
+ * with invalid indices or null input, have been altered - see individual methods.
+ * The biggest of these changes is that by default, null will not output the text
+ * 'null'. This can be controlled by a property, {@link #setNullText(String)}.
+ *
+ * Prior to 3.0, this class implemented Cloneable but did not implement the
+ * clone method so could not be used. From 3.0 onwards it no longer implements
+ * the interface.
+ *
+ * @author Apache Software Foundation
+ * @since 2.2
+ * @version $Id$
+ */
+public class StrBuilder implements Cloneable {
+
+ /**
+ * The extra capacity for new builders.
+ */
+ static final int CAPACITY = 32;
+
+ /**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = 7628716375283629643L;
+
+ /** Internal data storage. */
+ protected char[] buffer; // TODO make private?
+ /** Current size of the buffer. */
+ protected int size; // TODO make private?
+ /** The new line. */
+ private String newLine;
+ /** The null text. */
+ private String nullText;
+
+ //-----------------------------------------------------------------------
+ /**
+ * Constructor that creates an empty builder initial capacity 32 characters.
+ */
+ public StrBuilder() {
+ this(CAPACITY);
+ }
+
+ /**
+ * Constructor that creates an empty builder the specified initial capacity.
+ *
+ * @param initialCapacity the initial capacity, zero or less will be converted to 32
+ */
+ public StrBuilder(int initialCapacity) {
+ super();
+ if (initialCapacity <= 0) {
+ initialCapacity = CAPACITY;
+ }
+ buffer = new char[initialCapacity];
+ }
+
+ /**
+ * Constructor that creates a builder from the string, allocating
+ * 32 extra characters for growth.
+ *
+ * @param str the string to copy, null treated as blank string
+ */
+ public StrBuilder(String str) {
+ super();
+ if (str == null) {
+ buffer = new char[CAPACITY];
+ } else {
+ buffer = new char[str.length() + CAPACITY];
+ append(str);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the text to be appended when a new line is added.
+ *
+ * @return the new line text, null means use system default
+ */
+ public String getNewLineText() {
+ return newLine;
+ }
+
+ /**
+ * Sets the text to be appended when a new line is added.
+ *
+ * @param newLine the new line text, null means use system default
+ * @return this, to enable chaining
+ */
+ public StrBuilder setNewLineText(String newLine) {
+ this.newLine = newLine;
+ return this;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the text to be appended when null is added.
+ *
+ * @return the null text, null means no append
+ */
+ public String getNullText() {
+ return nullText;
+ }
+
+ /**
+ * Sets the text to be appended when null is added.
+ *
+ * @param nullText the null text, null means no append
+ * @return this, to enable chaining
+ */
+ public StrBuilder setNullText(String nullText) {
+ if (nullText != null && nullText.length() == 0) {
+ nullText = null;
+ }
+ this.nullText = nullText;
+ return this;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the length of the string builder.
+ *
+ * @return the length
+ */
+ public int length() {
+ return size;
+ }
+
+ /**
+ * Updates the length of the builder by either dropping the last characters
+ * or adding filler of unicode zero.
+ *
+ * @param length the length to set to, must be zero or positive
+ * @return this, to enable chaining
+ * @throws IndexOutOfBoundsException if the length is negative
+ */
+ public StrBuilder setLength(int length) {
+ if (length < 0) {
+ throw new StringIndexOutOfBoundsException(length);
+ }
+ if (length < size) {
+ size = length;
+ } else if (length > size) {
+ ensureCapacity(length);
+ int oldEnd = size;
+ int newEnd = length;
+ size = length;
+ for (int i = oldEnd; i < newEnd; i++) {
+ buffer[i] = '\0';
+ }
+ }
+ return this;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the current size of the internal character array buffer.
+ *
+ * @return the capacity
+ */
+ public int capacity() {
+ return buffer.length;
+ }
+
+ /**
+ * Checks the capacity and ensures that it is at least the size specified.
+ *
+ * @param capacity the capacity to ensure
+ * @return this, to enable chaining
+ */
+ public StrBuilder ensureCapacity(int capacity) {
+ if (capacity > buffer.length) {
+ char[] old = buffer;
+ buffer = new char[capacity * 2];
+ System.arraycopy(old, 0, buffer, 0, size);
+ }
+ return this;
+ }
+
+ /**
+ * Minimizes the capacity to the actual length of the string.
+ *
+ * @return this, to enable chaining
+ */
+ public StrBuilder minimizeCapacity() {
+ if (buffer.length > length()) {
+ char[] old = buffer;
+ buffer = new char[length()];
+ System.arraycopy(old, 0, buffer, 0, size);
+ }
+ return this;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the length of the string builder.
+ *
+ * This method is the same as {@link #length()} and is provided to match the
+ * API of Collections.
+ *
+ * @return the length
+ */
+ public int size() {
+ return size;
+ }
+
+ /**
+ * Checks is the string builder is empty (convenience Collections API style method).
+ *
+ * This method is the same as checking {@link #length()} and is provided to match the
+ * API of Collections.
+ *
+ * @return true
if the size is 0
.
+ */
+ public boolean isEmpty() {
+ return size == 0;
+ }
+
+ /**
+ * Clears the string builder (convenience Collections API style method).
+ *
+ * This method does not reduce the size of the internal character buffer.
+ * To do that, call clear()
followed by {@link #minimizeCapacity()}.
+ *
+ * This method is the same as {@link #setLength(int)} called with zero
+ * and is provided to match the API of Collections.
+ *
+ * @return this, to enable chaining
+ */
+ public StrBuilder clear() {
+ size = 0;
+ return this;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the character at the specified index.
+ *
+ * @see #setCharAt(int, char)
+ * @see #deleteCharAt(int)
+ * @param index the index to retrieve, must be valid
+ * @return the character at the index
+ * @throws IndexOutOfBoundsException if the index is invalid
+ */
+ public char charAt(int index) {
+ if (index < 0 || index >= length()) {
+ throw new StringIndexOutOfBoundsException(index);
+ }
+ return buffer[index];
+ }
+
+ /**
+ * Sets the character at the specified index.
+ *
+ * @see #charAt(int)
+ * @see #deleteCharAt(int)
+ * @param index the index to set
+ * @param ch the new character
+ * @return this, to enable chaining
+ * @throws IndexOutOfBoundsException if the index is invalid
+ */
+ public StrBuilder setCharAt(int index, char ch) {
+ if (index < 0 || index >= length()) {
+ throw new StringIndexOutOfBoundsException(index);
+ }
+ buffer[index] = ch;
+ return this;
+ }
+
+ /**
+ * Deletes the character at the specified index.
+ *
+ * @see #charAt(int)
+ * @see #setCharAt(int, char)
+ * @param index the index to delete
+ * @return this, to enable chaining
+ * @throws IndexOutOfBoundsException if the index is invalid
+ */
+ public StrBuilder deleteCharAt(int index) {
+ if (index < 0 || index >= size) {
+ throw new StringIndexOutOfBoundsException(index);
+ }
+ deleteImpl(index, index + 1, 1);
+ return this;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Copies the builder's character array into a new character array.
+ *
+ * @return a new array that represents the contents of the builder
+ */
+ public char[] toCharArray() {
+ if (size == 0) {
+ return ArrayUtils.EMPTY_CHAR_ARRAY;
+ }
+ char chars[] = new char[size];
+ System.arraycopy(buffer, 0, chars, 0, size);
+ return chars;
+ }
+
+ /**
+ * Copies part of the builder's character array into a new character array.
+ *
+ * @param startIndex the start index, inclusive, must be valid
+ * @param endIndex the end index, exclusive, must be valid except that
+ * if too large it is treated as end of string
+ * @return a new array that holds part of the contents of the builder
+ * @throws IndexOutOfBoundsException if startIndex is invalid,
+ * or if endIndex is invalid (but endIndex greater than size is valid)
+ */
+ public char[] toCharArray(int startIndex, int endIndex) {
+ endIndex = validateRange(startIndex, endIndex);
+ int len = endIndex - startIndex;
+ if (len == 0) {
+ return ArrayUtils.EMPTY_CHAR_ARRAY;
+ }
+ char chars[] = new char[len];
+ System.arraycopy(buffer, startIndex, chars, 0, len);
+ return chars;
+ }
+
+ /**
+ * Copies the character array into the specified array.
+ *
+ * @param destination the destination array, null will cause an array to be created
+ * @return the input array, unless that was null or too small
+ */
+ public char[] getChars(char[] destination) {
+ int len = length();
+ if (destination == null || destination.length < len) {
+ destination = new char[len];
+ }
+ System.arraycopy(buffer, 0, destination, 0, len);
+ return destination;
+ }
+
+ /**
+ * Copies the character array into the specified array.
+ *
+ * @param startIndex first index to copy, inclusive, must be valid
+ * @param endIndex last index, exclusive, must be valid
+ * @param destination the destination array, must not be null or too small
+ * @param destinationIndex the index to start copying in destination
+ * @throws NullPointerException if the array is null
+ * @throws IndexOutOfBoundsException if any index is invalid
+ */
+ public void getChars(int startIndex, int endIndex, char destination[], int destinationIndex) {
+ if (startIndex < 0) {
+ throw new StringIndexOutOfBoundsException(startIndex);
+ }
+ if (endIndex < 0 || endIndex > length()) {
+ throw new StringIndexOutOfBoundsException(endIndex);
+ }
+ if (startIndex > endIndex) {
+ throw new StringIndexOutOfBoundsException("end < start");
+ }
+ System.arraycopy(buffer, startIndex, destination, destinationIndex, endIndex - startIndex);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Appends the new line string to this string builder.
+ *
+ * The new line string can be altered using {@link #setNewLineText(String)}.
+ * This might be used to force the output to always use Unix line endings
+ * even when on Windows.
+ *
+ * @return this, to enable chaining
+ */
+ public StrBuilder appendNewLine() {
+ if (newLine == null) {
+ append(SystemUtils.LINE_SEPARATOR);
+ return this;
+ }
+ return append(newLine);
+ }
+
+ /**
+ * Appends the text representing null
to this string builder.
+ *
+ * @return this, to enable chaining
+ */
+ public StrBuilder appendNull() {
+ if (nullText == null) {
+ return this;
+ }
+ return append(nullText);
+ }
+
+ /**
+ * Appends an object to this string builder.
+ * Appending null will call {@link #appendNull()}.
+ *
+ * @param obj the object to append
+ * @return this, to enable chaining
+ */
+ public StrBuilder append(Object obj) {
+ if (obj == null) {
+ return appendNull();
+ }
+ return append(obj.toString());
+ }
+
+ /**
+ * Appends a string to this string builder.
+ * Appending null will call {@link #appendNull()}.
+ *
+ * @param str the string to append
+ * @return this, to enable chaining
+ */
+ public StrBuilder append(String str) {
+ if (str == null) {
+ return appendNull();
+ }
+ int strLen = str.length();
+ if (strLen > 0) {
+ int len = length();
+ ensureCapacity(len + strLen);
+ str.getChars(0, strLen, buffer, len);
+ size += strLen;
+ }
+ return this;
+ }
+
+ /**
+ * Appends part of a string to this string builder.
+ * Appending null will call {@link #appendNull()}.
+ *
+ * @param str the string to append
+ * @param startIndex the start index, inclusive, must be valid
+ * @param length the length to append, must be valid
+ * @return this, to enable chaining
+ */
+ public StrBuilder append(String str, int startIndex, int length) {
+ if (str == null) {
+ return appendNull();
+ }
+ if (startIndex < 0 || startIndex > str.length()) {
+ throw new StringIndexOutOfBoundsException("startIndex must be valid");
+ }
+ if (length < 0 || (startIndex + length) > str.length()) {
+ throw new StringIndexOutOfBoundsException("length must be valid");
+ }
+ if (length > 0) {
+ int len = length();
+ ensureCapacity(len + length);
+ str.getChars(startIndex, startIndex + length, buffer, len);
+ size += length;
+ }
+ return this;
+ }
+
+ /**
+ * Appends a string buffer to this string builder.
+ * Appending null will call {@link #appendNull()}.
+ *
+ * @param str the string buffer to append
+ * @return this, to enable chaining
+ */
+ public StrBuilder append(StringBuffer str) {
+ if (str == null) {
+ return appendNull();
+ }
+ int strLen = str.length();
+ if (strLen > 0) {
+ int len = length();
+ ensureCapacity(len + strLen);
+ str.getChars(0, strLen, buffer, len);
+ size += strLen;
+ }
+ return this;
+ }
+
+ /**
+ * Appends part of a string buffer to this string builder.
+ * Appending null will call {@link #appendNull()}.
+ *
+ * @param str the string to append
+ * @param startIndex the start index, inclusive, must be valid
+ * @param length the length to append, must be valid
+ * @return this, to enable chaining
+ */
+ public StrBuilder append(StringBuffer str, int startIndex, int length) {
+ if (str == null) {
+ return appendNull();
+ }
+ if (startIndex < 0 || startIndex > str.length()) {
+ throw new StringIndexOutOfBoundsException("startIndex must be valid");
+ }
+ if (length < 0 || (startIndex + length) > str.length()) {
+ throw new StringIndexOutOfBoundsException("length must be valid");
+ }
+ if (length > 0) {
+ int len = length();
+ ensureCapacity(len + length);
+ str.getChars(startIndex, startIndex + length, buffer, len);
+ size += length;
+ }
+ return this;
+ }
+
+ /**
+ * Appends another string builder to this string builder.
+ * Appending null will call {@link #appendNull()}.
+ *
+ * @param str the string builder to append
+ * @return this, to enable chaining
+ */
+ public StrBuilder append(StrBuilder str) {
+ if (str == null) {
+ return appendNull();
+ }
+ int strLen = str.length();
+ if (strLen > 0) {
+ int len = length();
+ ensureCapacity(len + strLen);
+ System.arraycopy(str.buffer, 0, buffer, len, strLen);
+ size += strLen;
+ }
+ return this;
+ }
+
+ /**
+ * Appends part of a string builder to this string builder.
+ * Appending null will call {@link #appendNull()}.
+ *
+ * @param str the string to append
+ * @param startIndex the start index, inclusive, must be valid
+ * @param length the length to append, must be valid
+ * @return this, to enable chaining
+ */
+ public StrBuilder append(StrBuilder str, int startIndex, int length) {
+ if (str == null) {
+ return appendNull();
+ }
+ if (startIndex < 0 || startIndex > str.length()) {
+ throw new StringIndexOutOfBoundsException("startIndex must be valid");
+ }
+ if (length < 0 || (startIndex + length) > str.length()) {
+ throw new StringIndexOutOfBoundsException("length must be valid");
+ }
+ if (length > 0) {
+ int len = length();
+ ensureCapacity(len + length);
+ str.getChars(startIndex, startIndex + length, buffer, len);
+ size += length;
+ }
+ return this;
+ }
+
+ /**
+ * Appends a char array to the string builder.
+ * Appending null will call {@link #appendNull()}.
+ *
+ * @param chars the char array to append
+ * @return this, to enable chaining
+ */
+ public StrBuilder append(char[] chars) {
+ if (chars == null) {
+ return appendNull();
+ }
+ int strLen = chars.length;
+ if (strLen > 0) {
+ int len = length();
+ ensureCapacity(len + strLen);
+ System.arraycopy(chars, 0, buffer, len, strLen);
+ size += strLen;
+ }
+ return this;
+ }
+
+ /**
+ * Appends a char array to the string builder.
+ * Appending null will call {@link #appendNull()}.
+ *
+ * @param chars the char array to append
+ * @param startIndex the start index, inclusive, must be valid
+ * @param length the length to append, must be valid
+ * @return this, to enable chaining
+ */
+ public StrBuilder append(char[] chars, int startIndex, int length) {
+ if (chars == null) {
+ return appendNull();
+ }
+ if (startIndex < 0 || startIndex > chars.length) {
+ throw new StringIndexOutOfBoundsException("Invalid startIndex: " + length);
+ }
+ if (length < 0 || (startIndex + length) > chars.length) {
+ throw new StringIndexOutOfBoundsException("Invalid length: " + length);
+ }
+ if (length > 0) {
+ int len = length();
+ ensureCapacity(len + length);
+ System.arraycopy(chars, startIndex, buffer, len, length);
+ size += length;
+ }
+ return this;
+ }
+
+ /**
+ * Appends a boolean value to the string builder.
+ *
+ * @param value the value to append
+ * @return this, to enable chaining
+ */
+ public StrBuilder append(boolean value) {
+ if (value) {
+ ensureCapacity(size + 4);
+ buffer[size++] = 't';
+ buffer[size++] = 'r';
+ buffer[size++] = 'u';
+ buffer[size++] = 'e';
+ } else {
+ ensureCapacity(size + 5);
+ buffer[size++] = 'f';
+ buffer[size++] = 'a';
+ buffer[size++] = 'l';
+ buffer[size++] = 's';
+ buffer[size++] = 'e';
+ }
+ return this;
+ }
+
+ /**
+ * Appends a char value to the string builder.
+ *
+ * @param ch the value to append
+ * @return this, to enable chaining
+ */
+ public StrBuilder append(char ch) {
+ int len = length();
+ ensureCapacity(len + 1);
+ buffer[size++] = ch;
+ return this;
+ }
+
+ /**
+ * Appends an int value to the string builder using String.valueOf
.
+ *
+ * @param value the value to append
+ * @return this, to enable chaining
+ */
+ public StrBuilder append(int value) {
+ return append(String.valueOf(value));
+ }
+
+ /**
+ * Appends a long value to the string builder using String.valueOf
.
+ *
+ * @param value the value to append
+ * @return this, to enable chaining
+ */
+ public StrBuilder append(long value) {
+ return append(String.valueOf(value));
+ }
+
+ /**
+ * Appends a float value to the string builder using String.valueOf
.
+ *
+ * @param value the value to append
+ * @return this, to enable chaining
+ */
+ public StrBuilder append(float value) {
+ return append(String.valueOf(value));
+ }
+
+ /**
+ * Appends a double value to the string builder using String.valueOf
.
+ *
+ * @param value the value to append
+ * @return this, to enable chaining
+ */
+ public StrBuilder append(double value) {
+ return append(String.valueOf(value));
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Appends an object followed by a new line to this string builder.
+ * Appending null will call {@link #appendNull()}.
+ *
+ * @param obj the object to append
+ * @return this, to enable chaining
+ * @since 2.3
+ */
+ public StrBuilder appendln(Object obj) {
+ return append(obj).appendNewLine();
+ }
+
+ /**
+ * Appends a string followed by a new line to this string builder.
+ * Appending null will call {@link #appendNull()}.
+ *
+ * @param str the string to append
+ * @return this, to enable chaining
+ * @since 2.3
+ */
+ public StrBuilder appendln(String str) {
+ return append(str).appendNewLine();
+ }
+
+ /**
+ * Appends part of a string followed by a new line to this string builder.
+ * Appending null will call {@link #appendNull()}.
+ *
+ * @param str the string to append
+ * @param startIndex the start index, inclusive, must be valid
+ * @param length the length to append, must be valid
+ * @return this, to enable chaining
+ * @since 2.3
+ */
+ public StrBuilder appendln(String str, int startIndex, int length) {
+ return append(str, startIndex, length).appendNewLine();
+ }
+
+ /**
+ * Appends a string buffer followed by a new line to this string builder.
+ * Appending null will call {@link #appendNull()}.
+ *
+ * @param str the string buffer to append
+ * @return this, to enable chaining
+ * @since 2.3
+ */
+ public StrBuilder appendln(StringBuffer str) {
+ return append(str).appendNewLine();
+ }
+
+ /**
+ * Appends part of a string buffer followed by a new line to this string builder.
+ * Appending null will call {@link #appendNull()}.
+ *
+ * @param str the string to append
+ * @param startIndex the start index, inclusive, must be valid
+ * @param length the length to append, must be valid
+ * @return this, to enable chaining
+ * @since 2.3
+ */
+ public StrBuilder appendln(StringBuffer str, int startIndex, int length) {
+ return append(str, startIndex, length).appendNewLine();
+ }
+
+ /**
+ * Appends another string builder followed by a new line to this string builder.
+ * Appending null will call {@link #appendNull()}.
+ *
+ * @param str the string builder to append
+ * @return this, to enable chaining
+ * @since 2.3
+ */
+ public StrBuilder appendln(StrBuilder str) {
+ return append(str).appendNewLine();
+ }
+
+ /**
+ * Appends part of a string builder followed by a new line to this string builder.
+ * Appending null will call {@link #appendNull()}.
+ *
+ * @param str the string to append
+ * @param startIndex the start index, inclusive, must be valid
+ * @param length the length to append, must be valid
+ * @return this, to enable chaining
+ * @since 2.3
+ */
+ public StrBuilder appendln(StrBuilder str, int startIndex, int length) {
+ return append(str, startIndex, length).appendNewLine();
+ }
+
+ /**
+ * Appends a char array followed by a new line to the string builder.
+ * Appending null will call {@link #appendNull()}.
+ *
+ * @param chars the char array to append
+ * @return this, to enable chaining
+ * @since 2.3
+ */
+ public StrBuilder appendln(char[] chars) {
+ return append(chars).appendNewLine();
+ }
+
+ /**
+ * Appends a char array followed by a new line to the string builder.
+ * Appending null will call {@link #appendNull()}.
+ *
+ * @param chars the char array to append
+ * @param startIndex the start index, inclusive, must be valid
+ * @param length the length to append, must be valid
+ * @return this, to enable chaining
+ * @since 2.3
+ */
+ public StrBuilder appendln(char[] chars, int startIndex, int length) {
+ return append(chars, startIndex, length).appendNewLine();
+ }
+
+ /**
+ * Appends a boolean value followed by a new line to the string builder.
+ *
+ * @param value the value to append
+ * @return this, to enable chaining
+ * @since 2.3
+ */
+ public StrBuilder appendln(boolean value) {
+ return append(value).appendNewLine();
+ }
+
+ /**
+ * Appends a char value followed by a new line to the string builder.
+ *
+ * @param ch the value to append
+ * @return this, to enable chaining
+ * @since 2.3
+ */
+ public StrBuilder appendln(char ch) {
+ return append(ch).appendNewLine();
+ }
+
+ /**
+ * Appends an int value followed by a new line to the string builder using String.valueOf
.
+ *
+ * @param value the value to append
+ * @return this, to enable chaining
+ * @since 2.3
+ */
+ public StrBuilder appendln(int value) {
+ return append(value).appendNewLine();
+ }
+
+ /**
+ * Appends a long value followed by a new line to the string builder using String.valueOf
.
+ *
+ * @param value the value to append
+ * @return this, to enable chaining
+ * @since 2.3
+ */
+ public StrBuilder appendln(long value) {
+ return append(value).appendNewLine();
+ }
+
+ /**
+ * Appends a float value followed by a new line to the string builder using String.valueOf
.
+ *
+ * @param value the value to append
+ * @return this, to enable chaining
+ * @since 2.3
+ */
+ public StrBuilder appendln(float value) {
+ return append(value).appendNewLine();
+ }
+
+ /**
+ * Appends a double value followed by a new line to the string builder using String.valueOf
.
+ *
+ * @param value the value to append
+ * @return this, to enable chaining
+ * @since 2.3
+ */
+ public StrBuilder appendln(double value) {
+ return append(value).appendNewLine();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Appends each item in an array to the builder without any separators.
+ * Appending a null array will have no effect.
+ * Each object is appended using {@link #append(Object)}.
+ *
+ * @param array the array to append
+ * @return this, to enable chaining
+ * @since 2.3
+ */
+ public StrBuilder appendAll(Object[] array) {
+ if (array != null && array.length > 0) {
+ for (int i = 0; i < array.length; i++) {
+ append(array[i]);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Appends each item in a collection to the builder without any separators.
+ * Appending a null collection will have no effect.
+ * Each object is appended using {@link #append(Object)}.
+ *
+ * @param coll the collection to append
+ * @return this, to enable chaining
+ * @since 2.3
+ */
+ public StrBuilder appendAll(Collection coll) {
+ if (coll != null && coll.size() > 0) {
+ Iterator it = coll.iterator();
+ while (it.hasNext()) {
+ append(it.next());
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Appends each item in an iterator to the builder without any separators.
+ * Appending a null iterator will have no effect.
+ * Each object is appended using {@link #append(Object)}.
+ *
+ * @param it the iterator to append
+ * @return this, to enable chaining
+ * @since 2.3
+ */
+ public StrBuilder appendAll(Iterator it) {
+ if (it != null) {
+ while (it.hasNext()) {
+ append(it.next());
+ }
+ }
+ return this;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Appends an array placing separators between each value, but
+ * not before the first or after the last.
+ * Appending a null array will have no effect.
+ * Each object is appended using {@link #append(Object)}.
+ *
+ * @param array the array to append
+ * @param separator the separator to use, null means no separator
+ * @return this, to enable chaining
+ */
+ public StrBuilder appendWithSeparators(Object[] array, String separator) {
+ if (array != null && array.length > 0) {
+ separator = (separator == null ? "" : separator);
+ append(array[0]);
+ for (int i = 1; i < array.length; i++) {
+ append(separator);
+ append(array[i]);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Appends a collection placing separators between each value, but
+ * not before the first or after the last.
+ * Appending a null collection will have no effect.
+ * Each object is appended using {@link #append(Object)}.
+ *
+ * @param coll the collection to append
+ * @param separator the separator to use, null means no separator
+ * @return this, to enable chaining
+ */
+ public StrBuilder appendWithSeparators(Collection coll, String separator) {
+ if (coll != null && coll.size() > 0) {
+ separator = (separator == null ? "" : separator);
+ Iterator it = coll.iterator();
+ while (it.hasNext()) {
+ append(it.next());
+ if (it.hasNext()) {
+ append(separator);
+ }
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Appends an iterator placing separators between each value, but
+ * not before the first or after the last.
+ * Appending a null iterator will have no effect.
+ * Each object is appended using {@link #append(Object)}.
+ *
+ * @param it the iterator to append
+ * @param separator the separator to use, null means no separator
+ * @return this, to enable chaining
+ */
+ public StrBuilder appendWithSeparators(Iterator it, String separator) {
+ if (it != null) {
+ separator = (separator == null ? "" : separator);
+ while (it.hasNext()) {
+ append(it.next());
+ if (it.hasNext()) {
+ append(separator);
+ }
+ }
+ }
+ return this;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Appends a separator if the builder is currently non-empty.
+ * Appending a null separator will have no effect.
+ * The separator is appended using {@link #append(String)}.
+ *
+ * This method is useful for adding a separator each time around the
+ * loop except the first.
+ *
+ * for (Iterator it = list.iterator(); it.hasNext(); ) {
+ * appendSeparator(",");
+ * append(it.next());
+ * }
+ *
+ * Note that for this simple example, you should use
+ * {@link #appendWithSeparators(Collection, String)}.
+ *
+ * @param separator the separator to use, null means no separator
+ * @return this, to enable chaining
+ * @since 2.3
+ */
+ public StrBuilder appendSeparator(String separator) {
+ return appendSeparator(separator, null);
+ }
+
+ /**
+ * Appends one of both separators to the StrBuilder.
+ * If the builder is currently empty it will append the defaultIfEmpty-separator
+ * Otherwise it will append the standard-separator
+ *
+ * Appending a null separator will have no effect.
+ * The separator is appended using {@link #append(String)}.
+ *
+ * This method is for example useful for constructing queries
+ *
+ * StrBuilder whereClause = new StrBuilder();
+ * if(searchCommand.getPriority() != null) {
+ * whereClause.appendSeparator(" and", " where");
+ * whereClause.append(" priority = ?")
+ * }
+ * if(searchCommand.getComponent() != null) {
+ * whereClause.appendSeparator(" and", " where");
+ * whereClause.append(" component = ?")
+ * }
+ * selectClause.append(whereClause)
+ *
+ *
+ * @param standard the separator if builder is not empty, null means no separator
+ * @param defaultIfEmpty the separator if builder is empty, null means no separator
+ * @return this, to enable chaining
+ * @since 2.5
+ */
+ public StrBuilder appendSeparator(String standard, String defaultIfEmpty) {
+ String str = isEmpty() ? defaultIfEmpty : standard;
+ if (str != null) {
+ append(str);
+ }
+ return this;
+ }
+
+ /**
+ * Appends a separator if the builder is currently non-empty.
+ * The separator is appended using {@link #append(char)}.
+ *
+ * This method is useful for adding a separator each time around the
+ * loop except the first.
+ *
+ * for (Iterator it = list.iterator(); it.hasNext(); ) {
+ * appendSeparator(',');
+ * append(it.next());
+ * }
+ *
+ * Note that for this simple example, you should use
+ * {@link #appendWithSeparators(Collection, String)}.
+ *
+ * @param separator the separator to use
+ * @return this, to enable chaining
+ * @since 2.3
+ */
+ public StrBuilder appendSeparator(char separator) {
+ if (size() > 0) {
+ append(separator);
+ }
+ return this;
+ }
+
+ /**
+ * Append one of both separators to the builder
+ * If the builder is currently empty it will append the defaultIfEmpty-separator
+ * Otherwise it will append the standard-separator
+ *
+ * The separator is appended using {@link #append(char)}.
+ * @param standard the separator if builder is not empty
+ * @param defaultIfEmpty the separator if builder is empty
+ * @return this, to enable chaining
+ * @since 2.5
+ */
+ public StrBuilder appendSeparator(char standard, char defaultIfEmpty) {
+ if (size() > 0) {
+ append(standard);
+ }
+ else {
+ append(defaultIfEmpty);
+ }
+ return this;
+ }
+ /**
+ * Appends a separator to the builder if the loop index is greater than zero.
+ * Appending a null separator will have no effect.
+ * The separator is appended using {@link #append(String)}.
+ *
+ * This method is useful for adding a separator each time around the
+ * loop except the first.
+ *
+ * for (int i = 0; i < list.size(); i++) {
+ * appendSeparator(",", i);
+ * append(list.get(i));
+ * }
+ *
+ * Note that for this simple example, you should use
+ * {@link #appendWithSeparators(Collection, String)}.
+ *
+ * @param separator the separator to use, null means no separator
+ * @param loopIndex the loop index
+ * @return this, to enable chaining
+ * @since 2.3
+ */
+ public StrBuilder appendSeparator(String separator, int loopIndex) {
+ if (separator != null && loopIndex > 0) {
+ append(separator);
+ }
+ return this;
+ }
+
+ /**
+ * Appends a separator to the builder if the loop index is greater than zero.
+ * The separator is appended using {@link #append(char)}.
+ *
+ * This method is useful for adding a separator each time around the
+ * loop except the first.
+ *
+ * for (int i = 0; i < list.size(); i++) {
+ * appendSeparator(",", i);
+ * append(list.get(i));
+ * }
+ *
+ * Note that for this simple example, you should use
+ * {@link #appendWithSeparators(Collection, String)}.
+ *
+ * @param separator the separator to use
+ * @param loopIndex the loop index
+ * @return this, to enable chaining
+ * @since 2.3
+ */
+ public StrBuilder appendSeparator(char separator, int loopIndex) {
+ if (loopIndex > 0) {
+ append(separator);
+ }
+ return this;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Appends the pad character to the builder the specified number of times.
+ *
+ * @param length the length to append, negative means no append
+ * @param padChar the character to append
+ * @return this, to enable chaining
+ */
+ public StrBuilder appendPadding(int length, char padChar) {
+ if (length >= 0) {
+ ensureCapacity(size + length);
+ for (int i = 0; i < length; i++) {
+ buffer[size++] = padChar;
+ }
+ }
+ return this;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Appends an object to the builder padding on the left to a fixed width.
+ * The toString
of the object is used.
+ * If the object is larger than the length, the left hand side is lost.
+ * If the object is null, the null text value is used.
+ *
+ * @param obj the object to append, null uses null text
+ * @param width the fixed field width, zero or negative has no effect
+ * @param padChar the pad character to use
+ * @return this, to enable chaining
+ */
+ public StrBuilder appendFixedWidthPadLeft(Object obj, int width, char padChar) {
+ if (width > 0) {
+ ensureCapacity(size + width);
+ String str = (obj == null ? getNullText() : obj.toString());
+ if (str == null) {
+ str = "";
+ }
+ int strLen = str.length();
+ if (strLen >= width) {
+ str.getChars(strLen - width, strLen, buffer, size);
+ } else {
+ int padLen = width - strLen;
+ for (int i = 0; i < padLen; i++) {
+ buffer[size + i] = padChar;
+ }
+ str.getChars(0, strLen, buffer, size + padLen);
+ }
+ size += width;
+ }
+ return this;
+ }
+
+ /**
+ * Appends an object to the builder padding on the left to a fixed width.
+ * The String.valueOf
of the int
value is used.
+ * If the formatted value is larger than the length, the left hand side is lost.
+ *
+ * @param value the value to append
+ * @param width the fixed field width, zero or negative has no effect
+ * @param padChar the pad character to use
+ * @return this, to enable chaining
+ */
+ public StrBuilder appendFixedWidthPadLeft(int value, int width, char padChar) {
+ return appendFixedWidthPadLeft(String.valueOf(value), width, padChar);
+ }
+
+ /**
+ * Appends an object to the builder padding on the right to a fixed length.
+ * The toString
of the object is used.
+ * If the object is larger than the length, the right hand side is lost.
+ * If the object is null, null text value is used.
+ *
+ * @param obj the object to append, null uses null text
+ * @param width the fixed field width, zero or negative has no effect
+ * @param padChar the pad character to use
+ * @return this, to enable chaining
+ */
+ public StrBuilder appendFixedWidthPadRight(Object obj, int width, char padChar) {
+ if (width > 0) {
+ ensureCapacity(size + width);
+ String str = (obj == null ? getNullText() : obj.toString());
+ if (str == null) {
+ str = "";
+ }
+ int strLen = str.length();
+ if (strLen >= width) {
+ str.getChars(0, width, buffer, size);
+ } else {
+ int padLen = width - strLen;
+ str.getChars(0, strLen, buffer, size);
+ for (int i = 0; i < padLen; i++) {
+ buffer[size + strLen + i] = padChar;
+ }
+ }
+ size += width;
+ }
+ return this;
+ }
+
+ /**
+ * Appends an object to the builder padding on the right to a fixed length.
+ * The String.valueOf
of the int
value is used.
+ * If the object is larger than the length, the right hand side is lost.
+ *
+ * @param value the value to append
+ * @param width the fixed field width, zero or negative has no effect
+ * @param padChar the pad character to use
+ * @return this, to enable chaining
+ */
+ public StrBuilder appendFixedWidthPadRight(int value, int width, char padChar) {
+ return appendFixedWidthPadRight(String.valueOf(value), width, padChar);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Inserts the string representation of an object into this builder.
+ * Inserting null will use the stored null text value.
+ *
+ * @param index the index to add at, must be valid
+ * @param obj the object to insert
+ * @return this, to enable chaining
+ * @throws IndexOutOfBoundsException if the index is invalid
+ */
+ public StrBuilder insert(int index, Object obj) {
+ if (obj == null) {
+ return insert(index, nullText);
+ }
+ return insert(index, obj.toString());
+ }
+
+ /**
+ * Inserts the string into this builder.
+ * Inserting null will use the stored null text value.
+ *
+ * @param index the index to add at, must be valid
+ * @param str the string to insert
+ * @return this, to enable chaining
+ * @throws IndexOutOfBoundsException if the index is invalid
+ */
+ public StrBuilder insert(int index, String str) {
+ validateIndex(index);
+ if (str == null) {
+ str = nullText;
+ }
+ int strLen = (str == null ? 0 : str.length());
+ if (strLen > 0) {
+ int newSize = size + strLen;
+ ensureCapacity(newSize);
+ System.arraycopy(buffer, index, buffer, index + strLen, size - index);
+ size = newSize;
+ str.getChars(0, strLen, buffer, index); // str cannot be null here
+ }
+ return this;
+ }
+
+ /**
+ * Inserts the character array into this builder.
+ * Inserting null will use the stored null text value.
+ *
+ * @param index the index to add at, must be valid
+ * @param chars the char array to insert
+ * @return this, to enable chaining
+ * @throws IndexOutOfBoundsException if the index is invalid
+ */
+ public StrBuilder insert(int index, char chars[]) {
+ validateIndex(index);
+ if (chars == null) {
+ return insert(index, nullText);
+ }
+ int len = chars.length;
+ if (len > 0) {
+ ensureCapacity(size + len);
+ System.arraycopy(buffer, index, buffer, index + len, size - index);
+ System.arraycopy(chars, 0, buffer, index, len);
+ size += len;
+ }
+ return this;
+ }
+
+ /**
+ * Inserts part of the character array into this builder.
+ * Inserting null will use the stored null text value.
+ *
+ * @param index the index to add at, must be valid
+ * @param chars the char array to insert
+ * @param offset the offset into the character array to start at, must be valid
+ * @param length the length of the character array part to copy, must be positive
+ * @return this, to enable chaining
+ * @throws IndexOutOfBoundsException if any index is invalid
+ */
+ public StrBuilder insert(int index, char chars[], int offset, int length) {
+ validateIndex(index);
+ if (chars == null) {
+ return insert(index, nullText);
+ }
+ if (offset < 0 || offset > chars.length) {
+ throw new StringIndexOutOfBoundsException("Invalid offset: " + offset);
+ }
+ if (length < 0 || offset + length > chars.length) {
+ throw new StringIndexOutOfBoundsException("Invalid length: " + length);
+ }
+ if (length > 0) {
+ ensureCapacity(size + length);
+ System.arraycopy(buffer, index, buffer, index + length, size - index);
+ System.arraycopy(chars, offset, buffer, index, length);
+ size += length;
+ }
+ return this;
+ }
+
+ /**
+ * Inserts the value into this builder.
+ *
+ * @param index the index to add at, must be valid
+ * @param value the value to insert
+ * @return this, to enable chaining
+ * @throws IndexOutOfBoundsException if the index is invalid
+ */
+ public StrBuilder insert(int index, boolean value) {
+ validateIndex(index);
+ if (value) {
+ ensureCapacity(size + 4);
+ System.arraycopy(buffer, index, buffer, index + 4, size - index);
+ buffer[index++] = 't';
+ buffer[index++] = 'r';
+ buffer[index++] = 'u';
+ buffer[index] = 'e';
+ size += 4;
+ } else {
+ ensureCapacity(size + 5);
+ System.arraycopy(buffer, index, buffer, index + 5, size - index);
+ buffer[index++] = 'f';
+ buffer[index++] = 'a';
+ buffer[index++] = 'l';
+ buffer[index++] = 's';
+ buffer[index] = 'e';
+ size += 5;
+ }
+ return this;
+ }
+
+ /**
+ * Inserts the value into this builder.
+ *
+ * @param index the index to add at, must be valid
+ * @param value the value to insert
+ * @return this, to enable chaining
+ * @throws IndexOutOfBoundsException if the index is invalid
+ */
+ public StrBuilder insert(int index, char value) {
+ validateIndex(index);
+ ensureCapacity(size + 1);
+ System.arraycopy(buffer, index, buffer, index + 1, size - index);
+ buffer[index] = value;
+ size++;
+ return this;
+ }
+
+ /**
+ * Inserts the value into this builder.
+ *
+ * @param index the index to add at, must be valid
+ * @param value the value to insert
+ * @return this, to enable chaining
+ * @throws IndexOutOfBoundsException if the index is invalid
+ */
+ public StrBuilder insert(int index, int value) {
+ return insert(index, String.valueOf(value));
+ }
+
+ /**
+ * Inserts the value into this builder.
+ *
+ * @param index the index to add at, must be valid
+ * @param value the value to insert
+ * @return this, to enable chaining
+ * @throws IndexOutOfBoundsException if the index is invalid
+ */
+ public StrBuilder insert(int index, long value) {
+ return insert(index, String.valueOf(value));
+ }
+
+ /**
+ * Inserts the value into this builder.
+ *
+ * @param index the index to add at, must be valid
+ * @param value the value to insert
+ * @return this, to enable chaining
+ * @throws IndexOutOfBoundsException if the index is invalid
+ */
+ public StrBuilder insert(int index, float value) {
+ return insert(index, String.valueOf(value));
+ }
+
+ /**
+ * Inserts the value into this builder.
+ *
+ * @param index the index to add at, must be valid
+ * @param value the value to insert
+ * @return this, to enable chaining
+ * @throws IndexOutOfBoundsException if the index is invalid
+ */
+ public StrBuilder insert(int index, double value) {
+ return insert(index, String.valueOf(value));
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Internal method to delete a range without validation.
+ *
+ * @param startIndex the start index, must be valid
+ * @param endIndex the end index (exclusive), must be valid
+ * @param len the length, must be valid
+ * @throws IndexOutOfBoundsException if any index is invalid
+ */
+ private void deleteImpl(int startIndex, int endIndex, int len) {
+ System.arraycopy(buffer, endIndex, buffer, startIndex, size - endIndex);
+ size -= len;
+ }
+
+ /**
+ * Deletes the characters between the two specified indices.
+ *
+ * @param startIndex the start index, inclusive, must be valid
+ * @param endIndex the end index, exclusive, must be valid except
+ * that if too large it is treated as end of string
+ * @return this, to enable chaining
+ * @throws IndexOutOfBoundsException if the index is invalid
+ */
+ public StrBuilder delete(int startIndex, int endIndex) {
+ endIndex = validateRange(startIndex, endIndex);
+ int len = endIndex - startIndex;
+ if (len > 0) {
+ deleteImpl(startIndex, endIndex, len);
+ }
+ return this;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Deletes the character wherever it occurs in the builder.
+ *
+ * @param ch the character to delete
+ * @return this, to enable chaining
+ */
+ public StrBuilder deleteAll(char ch) {
+ for (int i = 0; i < size; i++) {
+ if (buffer[i] == ch) {
+ int start = i;
+ while (++i < size) {
+ if (buffer[i] != ch) {
+ break;
+ }
+ }
+ int len = i - start;
+ deleteImpl(start, i, len);
+ i -= len;
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Deletes the character wherever it occurs in the builder.
+ *
+ * @param ch the character to delete
+ * @return this, to enable chaining
+ */
+ public StrBuilder deleteFirst(char ch) {
+ for (int i = 0; i < size; i++) {
+ if (buffer[i] == ch) {
+ deleteImpl(i, i + 1, 1);
+ break;
+ }
+ }
+ return this;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Deletes the string wherever it occurs in the builder.
+ *
+ * @param str the string to delete, null causes no action
+ * @return this, to enable chaining
+ */
+ public StrBuilder deleteAll(String str) {
+ int len = (str == null ? 0 : str.length());
+ if (len > 0) {
+ int index = indexOf(str, 0);
+ while (index >= 0) {
+ deleteImpl(index, index + len, len);
+ index = indexOf(str, index);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Deletes the string wherever it occurs in the builder.
+ *
+ * @param str the string to delete, null causes no action
+ * @return this, to enable chaining
+ */
+ public StrBuilder deleteFirst(String str) {
+ int len = (str == null ? 0 : str.length());
+ if (len > 0) {
+ int index = indexOf(str, 0);
+ if (index >= 0) {
+ deleteImpl(index, index + len, len);
+ }
+ }
+ return this;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Deletes all parts of the builder that the matcher matches.
+ *
+ * Matchers can be used to perform advanced deletion behaviour.
+ * For example you could write a matcher to delete all occurances
+ * where the character 'a' is followed by a number.
+ *
+ * @param matcher the matcher to use to find the deletion, null causes no action
+ * @return this, to enable chaining
+ */
+ public StrBuilder deleteAll(StrMatcher matcher) {
+ return replace(matcher, null, 0, size, -1);
+ }
+
+ /**
+ * Deletes the first match within the builder using the specified matcher.
+ *
+ * Matchers can be used to perform advanced deletion behaviour.
+ * For example you could write a matcher to delete
+ * where the character 'a' is followed by a number.
+ *
+ * @param matcher the matcher to use to find the deletion, null causes no action
+ * @return this, to enable chaining
+ */
+ public StrBuilder deleteFirst(StrMatcher matcher) {
+ return replace(matcher, null, 0, size, 1);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Internal method to delete a range without validation.
+ *
+ * @param startIndex the start index, must be valid
+ * @param endIndex the end index (exclusive), must be valid
+ * @param removeLen the length to remove (endIndex - startIndex), must be valid
+ * @param insertStr the string to replace with, null means delete range
+ * @param insertLen the length of the insert string, must be valid
+ * @throws IndexOutOfBoundsException if any index is invalid
+ */
+ private void replaceImpl(int startIndex, int endIndex, int removeLen, String insertStr, int insertLen) {
+ int newSize = size - removeLen + insertLen;
+ if (insertLen != removeLen) {
+ ensureCapacity(newSize);
+ System.arraycopy(buffer, endIndex, buffer, startIndex + insertLen, size - endIndex);
+ size = newSize;
+ }
+ if (insertLen > 0) {
+ insertStr.getChars(0, insertLen, buffer, startIndex);
+ }
+ }
+
+ /**
+ * Replaces a portion of the string builder with another string.
+ * The length of the inserted string does not have to match the removed length.
+ *
+ * @param startIndex the start index, inclusive, must be valid
+ * @param endIndex the end index, exclusive, must be valid except
+ * that if too large it is treated as end of string
+ * @param replaceStr the string to replace with, null means delete range
+ * @return this, to enable chaining
+ * @throws IndexOutOfBoundsException if the index is invalid
+ */
+ public StrBuilder replace(int startIndex, int endIndex, String replaceStr) {
+ endIndex = validateRange(startIndex, endIndex);
+ int insertLen = (replaceStr == null ? 0 : replaceStr.length());
+ replaceImpl(startIndex, endIndex, endIndex - startIndex, replaceStr, insertLen);
+ return this;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Replaces the search character with the replace character
+ * throughout the builder.
+ *
+ * @param search the search character
+ * @param replace the replace character
+ * @return this, to enable chaining
+ */
+ public StrBuilder replaceAll(char search, char replace) {
+ if (search != replace) {
+ for (int i = 0; i < size; i++) {
+ if (buffer[i] == search) {
+ buffer[i] = replace;
+ }
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Replaces the first instance of the search character with the
+ * replace character in the builder.
+ *
+ * @param search the search character
+ * @param replace the replace character
+ * @return this, to enable chaining
+ */
+ public StrBuilder replaceFirst(char search, char replace) {
+ if (search != replace) {
+ for (int i = 0; i < size; i++) {
+ if (buffer[i] == search) {
+ buffer[i] = replace;
+ break;
+ }
+ }
+ }
+ return this;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Replaces the search string with the replace string throughout the builder.
+ *
+ * @param searchStr the search string, null causes no action to occur
+ * @param replaceStr the replace string, null is equivalent to an empty string
+ * @return this, to enable chaining
+ */
+ public StrBuilder replaceAll(String searchStr, String replaceStr) {
+ int searchLen = (searchStr == null ? 0 : searchStr.length());
+ if (searchLen > 0) {
+ int replaceLen = (replaceStr == null ? 0 : replaceStr.length());
+ int index = indexOf(searchStr, 0);
+ while (index >= 0) {
+ replaceImpl(index, index + searchLen, searchLen, replaceStr, replaceLen);
+ index = indexOf(searchStr, index + replaceLen);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Replaces the first instance of the search string with the replace string.
+ *
+ * @param searchStr the search string, null causes no action to occur
+ * @param replaceStr the replace string, null is equivalent to an empty string
+ * @return this, to enable chaining
+ */
+ public StrBuilder replaceFirst(String searchStr, String replaceStr) {
+ int searchLen = (searchStr == null ? 0 : searchStr.length());
+ if (searchLen > 0) {
+ int index = indexOf(searchStr, 0);
+ if (index >= 0) {
+ int replaceLen = (replaceStr == null ? 0 : replaceStr.length());
+ replaceImpl(index, index + searchLen, searchLen, replaceStr, replaceLen);
+ }
+ }
+ return this;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Replaces all matches within the builder with the replace string.
+ *
+ * Matchers can be used to perform advanced replace behaviour.
+ * For example you could write a matcher to replace all occurances
+ * where the character 'a' is followed by a number.
+ *
+ * @param matcher the matcher to use to find the deletion, null causes no action
+ * @param replaceStr the replace string, null is equivalent to an empty string
+ * @return this, to enable chaining
+ */
+ public StrBuilder replaceAll(StrMatcher matcher, String replaceStr) {
+ return replace(matcher, replaceStr, 0, size, -1);
+ }
+
+ /**
+ * Replaces the first match within the builder with the replace string.
+ *
+ * Matchers can be used to perform advanced replace behaviour.
+ * For example you could write a matcher to replace
+ * where the character 'a' is followed by a number.
+ *
+ * @param matcher the matcher to use to find the deletion, null causes no action
+ * @param replaceStr the replace string, null is equivalent to an empty string
+ * @return this, to enable chaining
+ */
+ public StrBuilder replaceFirst(StrMatcher matcher, String replaceStr) {
+ return replace(matcher, replaceStr, 0, size, 1);
+ }
+
+ // -----------------------------------------------------------------------
+ /**
+ * Advanced search and replaces within the builder using a matcher.
+ *
+ * Matchers can be used to perform advanced behaviour.
+ * For example you could write a matcher to delete all occurances
+ * where the character 'a' is followed by a number.
+ *
+ * @param matcher the matcher to use to find the deletion, null causes no action
+ * @param replaceStr the string to replace the match with, null is a delete
+ * @param startIndex the start index, inclusive, must be valid
+ * @param endIndex the end index, exclusive, must be valid except
+ * that if too large it is treated as end of string
+ * @param replaceCount the number of times to replace, -1 for replace all
+ * @return this, to enable chaining
+ * @throws IndexOutOfBoundsException if start index is invalid
+ */
+ public StrBuilder replace(
+ StrMatcher matcher, String replaceStr,
+ int startIndex, int endIndex, int replaceCount) {
+ endIndex = validateRange(startIndex, endIndex);
+ return replaceImpl(matcher, replaceStr, startIndex, endIndex, replaceCount);
+ }
+
+ /**
+ * Replaces within the builder using a matcher.
+ *
+ * Matchers can be used to perform advanced behaviour.
+ * For example you could write a matcher to delete all occurances
+ * where the character 'a' is followed by a number.
+ *
+ * @param matcher the matcher to use to find the deletion, null causes no action
+ * @param replaceStr the string to replace the match with, null is a delete
+ * @param from the start index, must be valid
+ * @param to the end index (exclusive), must be valid
+ * @param replaceCount the number of times to replace, -1 for replace all
+ * @return this, to enable chaining
+ * @throws IndexOutOfBoundsException if any index is invalid
+ */
+ private StrBuilder replaceImpl(
+ StrMatcher matcher, String replaceStr,
+ int from, int to, int replaceCount) {
+ if (matcher == null || size == 0) {
+ return this;
+ }
+ int replaceLen = (replaceStr == null ? 0 : replaceStr.length());
+ char[] buf = buffer;
+ for (int i = from; i < to && replaceCount != 0; i++) {
+ int removeLen = matcher.isMatch(buf, i, from, to);
+ if (removeLen > 0) {
+ replaceImpl(i, i + removeLen, removeLen, replaceStr, replaceLen);
+ to = to - removeLen + replaceLen;
+ i = i + replaceLen - 1;
+ if (replaceCount > 0) {
+ replaceCount--;
+ }
+ }
+ }
+ return this;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Reverses the string builder placing each character in the opposite index.
+ *
+ * @return this, to enable chaining
+ */
+ public StrBuilder reverse() {
+ if (size == 0) {
+ return this;
+ }
+
+ int half = size / 2;
+ char[] buf = buffer;
+ for (int leftIdx = 0, rightIdx = size - 1; leftIdx < half; leftIdx++,rightIdx--) {
+ char swap = buf[leftIdx];
+ buf[leftIdx] = buf[rightIdx];
+ buf[rightIdx] = swap;
+ }
+ return this;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Trims the builder by removing characters less than or equal to a space
+ * from the beginning and end.
+ *
+ * @return this, to enable chaining
+ */
+ public StrBuilder trim() {
+ if (size == 0) {
+ return this;
+ }
+ int len = size;
+ char[] buf = buffer;
+ int pos = 0;
+ while (pos < len && buf[pos] <= ' ') {
+ pos++;
+ }
+ while (pos < len && buf[len - 1] <= ' ') {
+ len--;
+ }
+ if (len < size) {
+ delete(len, size);
+ }
+ if (pos > 0) {
+ delete(0, pos);
+ }
+ return this;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Checks whether this builder starts with the specified string.
+ *
+ * Note that this method handles null input quietly, unlike String.
+ *
+ * @param str the string to search for, null returns false
+ * @return true if the builder starts with the string
+ */
+ public boolean startsWith(String str) {
+ if (str == null) {
+ return false;
+ }
+ int len = str.length();
+ if (len == 0) {
+ return true;
+ }
+ if (len > size) {
+ return false;
+ }
+ for (int i = 0; i < len; i++) {
+ if (buffer[i] != str.charAt(i)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks whether this builder ends with the specified string.
+ *
+ * Note that this method handles null input quietly, unlike String.
+ *
+ * @param str the string to search for, null returns false
+ * @return true if the builder ends with the string
+ */
+ public boolean endsWith(String str) {
+ if (str == null) {
+ return false;
+ }
+ int len = str.length();
+ if (len == 0) {
+ return true;
+ }
+ if (len > size) {
+ return false;
+ }
+ int pos = size - len;
+ for (int i = 0; i < len; i++,pos++) {
+ if (buffer[pos] != str.charAt(i)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Extracts a portion of this string builder as a string.
+ *
+ * @param start the start index, inclusive, must be valid
+ * @return the new string
+ * @throws IndexOutOfBoundsException if the index is invalid
+ */
+ public String substring(int start) {
+ return substring(start, size);
+ }
+
+ /**
+ * Extracts a portion of this string builder as a string.
+ *
+ * Note: This method treats an endIndex greater than the length of the
+ * builder as equal to the length of the builder, and continues
+ * without error, unlike StringBuffer or String.
+ *
+ * @param startIndex the start index, inclusive, must be valid
+ * @param endIndex the end index, exclusive, must be valid except
+ * that if too large it is treated as end of string
+ * @return the new string
+ * @throws IndexOutOfBoundsException if the index is invalid
+ */
+ public String substring(int startIndex, int endIndex) {
+ endIndex = validateRange(startIndex, endIndex);
+ return new String(buffer, startIndex, endIndex - startIndex);
+ }
+
+ /**
+ * Extracts the leftmost characters from the string builder without
+ * throwing an exception.
+ *
+ * This method extracts the left length
characters from
+ * the builder. If this many characters are not available, the whole
+ * builder is returned. Thus the returned string may be shorter than the
+ * length requested.
+ *
+ * @param length the number of characters to extract, negative returns empty string
+ * @return the new string
+ */
+ public String leftString(int length) {
+ if (length <= 0) {
+ return "";
+ } else if (length >= size) {
+ return new String(buffer, 0, size);
+ } else {
+ return new String(buffer, 0, length);
+ }
+ }
+
+ /**
+ * Extracts the rightmost characters from the string builder without
+ * throwing an exception.
+ *
+ * This method extracts the right length
characters from
+ * the builder. If this many characters are not available, the whole
+ * builder is returned. Thus the returned string may be shorter than the
+ * length requested.
+ *
+ * @param length the number of characters to extract, negative returns empty string
+ * @return the new string
+ */
+ public String rightString(int length) {
+ if (length <= 0) {
+ return "";
+ } else if (length >= size) {
+ return new String(buffer, 0, size);
+ } else {
+ return new String(buffer, size - length, length);
+ }
+ }
+
+ /**
+ * Extracts some characters from the middle of the string builder without
+ * throwing an exception.
+ *
+ * This method extracts length
characters from the builder
+ * at the specified index.
+ * If the index is negative it is treated as zero.
+ * If the index is greater than the builder size, it is treated as the builder size.
+ * If the length is negative, the empty string is returned.
+ * If insufficient characters are available in the builder, as much as possible is returned.
+ * Thus the returned string may be shorter than the length requested.
+ *
+ * @param index the index to start at, negative means zero
+ * @param length the number of characters to extract, negative returns empty string
+ * @return the new string
+ */
+ public String midString(int index, int length) {
+ if (index < 0) {
+ index = 0;
+ }
+ if (length <= 0 || index >= size) {
+ return "";
+ }
+ if (size <= index + length) {
+ return new String(buffer, index, size - index);
+ } else {
+ return new String(buffer, index, length);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Checks if the string builder contains the specified char.
+ *
+ * @param ch the character to find
+ * @return true if the builder contains the character
+ */
+ public boolean contains(char ch) {
+ char[] thisBuf = buffer;
+ for (int i = 0; i < this.size; i++) {
+ if (thisBuf[i] == ch) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Checks if the string builder contains the specified string.
+ *
+ * @param str the string to find
+ * @return true if the builder contains the string
+ */
+ public boolean contains(String str) {
+ return indexOf(str, 0) >= 0;
+ }
+
+ /**
+ * Checks if the string builder contains a string matched using the
+ * specified matcher.
+ *
+ * Matchers can be used to perform advanced searching behaviour.
+ * For example you could write a matcher to search for the character
+ * 'a' followed by a number.
+ *
+ * @param matcher the matcher to use, null returns -1
+ * @return true if the matcher finds a match in the builder
+ */
+ public boolean contains(StrMatcher matcher) {
+ return indexOf(matcher, 0) >= 0;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Searches the string builder to find the first reference to the specified char.
+ *
+ * @param ch the character to find
+ * @return the first index of the character, or -1 if not found
+ */
+ public int indexOf(char ch) {
+ return indexOf(ch, 0);
+ }
+
+ /**
+ * Searches the string builder to find the first reference to the specified char.
+ *
+ * @param ch the character to find
+ * @param startIndex the index to start at, invalid index rounded to edge
+ * @return the first index of the character, or -1 if not found
+ */
+ public int indexOf(char ch, int startIndex) {
+ startIndex = (startIndex < 0 ? 0 : startIndex);
+ if (startIndex >= size) {
+ return -1;
+ }
+ char[] thisBuf = buffer;
+ for (int i = startIndex; i < size; i++) {
+ if (thisBuf[i] == ch) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Searches the string builder to find the first reference to the specified string.
+ *
+ * Note that a null input string will return -1, whereas the JDK throws an exception.
+ *
+ * @param str the string to find, null returns -1
+ * @return the first index of the string, or -1 if not found
+ */
+ public int indexOf(String str) {
+ return indexOf(str, 0);
+ }
+
+ /**
+ * Searches the string builder to find the first reference to the specified
+ * string starting searching from the given index.
+ *
+ * Note that a null input string will return -1, whereas the JDK throws an exception.
+ *
+ * @param str the string to find, null returns -1
+ * @param startIndex the index to start at, invalid index rounded to edge
+ * @return the first index of the string, or -1 if not found
+ */
+ public int indexOf(String str, int startIndex) {
+ startIndex = (startIndex < 0 ? 0 : startIndex);
+ if (str == null || startIndex >= size) {
+ return -1;
+ }
+ int strLen = str.length();
+ if (strLen == 1) {
+ return indexOf(str.charAt(0), startIndex);
+ }
+ if (strLen == 0) {
+ return startIndex;
+ }
+ if (strLen > size) {
+ return -1;
+ }
+ char[] thisBuf = buffer;
+ int len = size - strLen + 1;
+ outer:
+ for (int i = startIndex; i < len; i++) {
+ for (int j = 0; j < strLen; j++) {
+ if (str.charAt(j) != thisBuf[i + j]) {
+ continue outer;
+ }
+ }
+ return i;
+ }
+ return -1;
+ }
+
+ /**
+ * Searches the string builder using the matcher to find the first match.
+ *
+ * Matchers can be used to perform advanced searching behaviour.
+ * For example you could write a matcher to find the character 'a'
+ * followed by a number.
+ *
+ * @param matcher the matcher to use, null returns -1
+ * @return the first index matched, or -1 if not found
+ */
+ public int indexOf(StrMatcher matcher) {
+ return indexOf(matcher, 0);
+ }
+
+ /**
+ * Searches the string builder using the matcher to find the first
+ * match searching from the given index.
+ *
+ * Matchers can be used to perform advanced searching behaviour.
+ * For example you could write a matcher to find the character 'a'
+ * followed by a number.
+ *
+ * @param matcher the matcher to use, null returns -1
+ * @param startIndex the index to start at, invalid index rounded to edge
+ * @return the first index matched, or -1 if not found
+ */
+ public int indexOf(StrMatcher matcher, int startIndex) {
+ startIndex = (startIndex < 0 ? 0 : startIndex);
+ if (matcher == null || startIndex >= size) {
+ return -1;
+ }
+ int len = size;
+ char[] buf = buffer;
+ for (int i = startIndex; i < len; i++) {
+ if (matcher.isMatch(buf, i, startIndex, len) > 0) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Searches the string builder to find the last reference to the specified char.
+ *
+ * @param ch the character to find
+ * @return the last index of the character, or -1 if not found
+ */
+ public int lastIndexOf(char ch) {
+ return lastIndexOf(ch, size - 1);
+ }
+
+ /**
+ * Searches the string builder to find the last reference to the specified char.
+ *
+ * @param ch the character to find
+ * @param startIndex the index to start at, invalid index rounded to edge
+ * @return the last index of the character, or -1 if not found
+ */
+ public int lastIndexOf(char ch, int startIndex) {
+ startIndex = (startIndex >= size ? size - 1 : startIndex);
+ if (startIndex < 0) {
+ return -1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (buffer[i] == ch) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Searches the string builder to find the last reference to the specified string.
+ *
+ * Note that a null input string will return -1, whereas the JDK throws an exception.
+ *
+ * @param str the string to find, null returns -1
+ * @return the last index of the string, or -1 if not found
+ */
+ public int lastIndexOf(String str) {
+ return lastIndexOf(str, size - 1);
+ }
+
+ /**
+ * Searches the string builder to find the last reference to the specified
+ * string starting searching from the given index.
+ *
+ * Note that a null input string will return -1, whereas the JDK throws an exception.
+ *
+ * @param str the string to find, null returns -1
+ * @param startIndex the index to start at, invalid index rounded to edge
+ * @return the last index of the string, or -1 if not found
+ */
+ public int lastIndexOf(String str, int startIndex) {
+ startIndex = (startIndex >= size ? size - 1 : startIndex);
+ if (str == null || startIndex < 0) {
+ return -1;
+ }
+ int strLen = str.length();
+ if (strLen > 0 && strLen <= size) {
+ if (strLen == 1) {
+ return lastIndexOf(str.charAt(0), startIndex);
+ }
+
+ outer:
+ for (int i = startIndex - strLen + 1; i >= 0; i--) {
+ for (int j = 0; j < strLen; j++) {
+ if (str.charAt(j) != buffer[i + j]) {
+ continue outer;
+ }
+ }
+ return i;
+ }
+
+ } else if (strLen == 0) {
+ return startIndex;
+ }
+ return -1;
+ }
+
+ /**
+ * Searches the string builder using the matcher to find the last match.
+ *
+ * Matchers can be used to perform advanced searching behaviour.
+ * For example you could write a matcher to find the character 'a'
+ * followed by a number.
+ *
+ * @param matcher the matcher to use, null returns -1
+ * @return the last index matched, or -1 if not found
+ */
+ public int lastIndexOf(StrMatcher matcher) {
+ return lastIndexOf(matcher, size);
+ }
+
+ /**
+ * Searches the string builder using the matcher to find the last
+ * match searching from the given index.
+ *
+ * Matchers can be used to perform advanced searching behaviour.
+ * For example you could write a matcher to find the character 'a'
+ * followed by a number.
+ *
+ * @param matcher the matcher to use, null returns -1
+ * @param startIndex the index to start at, invalid index rounded to edge
+ * @return the last index matched, or -1 if not found
+ */
+ public int lastIndexOf(StrMatcher matcher, int startIndex) {
+ startIndex = (startIndex >= size ? size - 1 : startIndex);
+ if (matcher == null || startIndex < 0) {
+ return -1;
+ }
+ char[] buf = buffer;
+ int endIndex = startIndex + 1;
+ for (int i = startIndex; i >= 0; i--) {
+ if (matcher.isMatch(buf, i, 0, endIndex) > 0) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Creates a tokenizer that can tokenize the contents of this builder.
+ *
+ * This method allows the contents of this builder to be tokenized.
+ * The tokenizer will be setup by default to tokenize on space, tab,
+ * newline and formfeed (as per StringTokenizer). These values can be
+ * changed on the tokenizer class, before retrieving the tokens.
+ *
+ * The returned tokenizer is linked to this builder. You may intermix
+ * calls to the buider and tokenizer within certain limits, however
+ * there is no synchronization. Once the tokenizer has been used once,
+ * it must be {@link StrTokenizer#reset() reset} to pickup the latest
+ * changes in the builder. For example:
+ *
+ * StrBuilder b = new StrBuilder();
+ * b.append("a b ");
+ * StrTokenizer t = b.asTokenizer();
+ * String[] tokens1 = t.getTokenArray(); // returns a,b
+ * b.append("c d ");
+ * String[] tokens2 = t.getTokenArray(); // returns a,b (c and d ignored)
+ * t.reset(); // reset causes builder changes to be picked up
+ * String[] tokens3 = t.getTokenArray(); // returns a,b,c,d
+ *
+ * In addition to simply intermixing appends and tokenization, you can also
+ * call the set methods on the tokenizer to alter how it tokenizes. Just
+ * remember to call reset when you want to pickup builder changes.
+ *
+ * Calling {@link StrTokenizer#reset(String)} or {@link StrTokenizer#reset(char[])}
+ * with a non-null value will break the link with the builder.
+ *
+ * @return a tokenizer that is linked to this builder
+ */
+ public StrTokenizer asTokenizer() {
+ return new StrBuilderTokenizer();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the contents of this builder as a Reader.
+ *
+ * This method allows the contents of the builder to be read
+ * using any standard method that expects a Reader.
+ *
+ * To use, simply create a StrBuilder
, populate it with
+ * data, call asReader
, and then read away.
+ *
+ * The internal character array is shared between the builder and the reader.
+ * This allows you to append to the builder after creating the reader,
+ * and the changes will be picked up.
+ * Note however, that no synchronization occurs, so you must perform
+ * all operations with the builder and the reader in one thread.
+ *
+ * The returned reader supports marking, and ignores the flush method.
+ *
+ * @return a reader that reads from this builder
+ */
+ public Reader asReader() {
+ return new StrBuilderReader();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets this builder as a Writer that can be written to.
+ *
+ * This method allows you to populate the contents of the builder
+ * using any standard method that takes a Writer.
+ *
+ * To use, simply create a StrBuilder
,
+ * call asWriter
, and populate away. The data is available
+ * at any time using the methods of the StrBuilder
.
+ *
+ * The internal character array is shared between the builder and the writer.
+ * This allows you to intermix calls that append to the builder and
+ * write using the writer and the changes will be occur correctly.
+ * Note however, that no synchronization occurs, so you must perform
+ * all operations with the builder and the writer in one thread.
+ *
+ * The returned writer ignores the close and flush methods.
+ *
+ * @return a writer that populates this builder
+ */
+ public Writer asWriter() {
+ return new StrBuilderWriter();
+ }
+
+ //-----------------------------------------------------------------------
+// /**
+// * Gets a String version of the string builder by calling the internal
+// * constructor of String by reflection.
+// *
+// * WARNING: You must not use the StrBuilder after calling this method
+// * as the buffer is now shared with the String object. To ensure this,
+// * the internal character array is set to null, so you will get
+// * NullPointerExceptions on all method calls.
+// *
+// * @return the builder as a String
+// */
+// public String toSharedString() {
+// try {
+// Constructor con = String.class.getDeclaredConstructor(
+// new Class[] {int.class, int.class, char[].class});
+// con.setAccessible(true);
+// char[] buffer = buf;
+// buf = null;
+// size = -1;
+// nullText = null;
+// return (String) con.newInstance(
+// new Object[] {new Integer(0), new Integer(size), buffer});
+//
+// } catch (Exception ex) {
+// ex.printStackTrace();
+// throw new UnsupportedOperationException("StrBuilder.toSharedString is unsupported: " + ex.getMessage());
+// }
+// }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Checks the contents of this builder against another to see if they
+ * contain the same character content ignoring case.
+ *
+ * @param other the object to check, null returns false
+ * @return true if the builders contain the same characters in the same order
+ */
+ public boolean equalsIgnoreCase(StrBuilder other) {
+ if (this == other) {
+ return true;
+ }
+ if (this.size != other.size) {
+ return false;
+ }
+ char thisBuf[] = this.buffer;
+ char otherBuf[] = other.buffer;
+ for (int i = size - 1; i >= 0; i--) {
+ char c1 = thisBuf[i];
+ char c2 = otherBuf[i];
+ if (c1 != c2 && Character.toUpperCase(c1) != Character.toUpperCase(c2)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks the contents of this builder against another to see if they
+ * contain the same character content.
+ *
+ * @param other the object to check, null returns false
+ * @return true if the builders contain the same characters in the same order
+ */
+ public boolean equals(StrBuilder other) {
+ if (this == other) {
+ return true;
+ }
+ if (this.size != other.size) {
+ return false;
+ }
+ char thisBuf[] = this.buffer;
+ char otherBuf[] = other.buffer;
+ for (int i = size - 1; i >= 0; i--) {
+ if (thisBuf[i] != otherBuf[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks the contents of this builder against another to see if they
+ * contain the same character content.
+ *
+ * @param obj the object to check, null returns false
+ * @return true if the builders contain the same characters in the same order
+ */
+ public boolean equals(Object obj) {
+ if (obj instanceof StrBuilder) {
+ return equals((StrBuilder) obj);
+ }
+ return false;
+ }
+
+ /**
+ * Gets a suitable hash code for this builder.
+ *
+ * @return a hash code
+ */
+ public int hashCode() {
+ char buf[] = buffer;
+ int hash = 0;
+ for (int i = size - 1; i >= 0; i--) {
+ hash = 31 * hash + buf[i];
+ }
+ return hash;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets a String version of the string builder, creating a new instance
+ * each time the method is called.
+ *
+ * Note that unlike StringBuffer, the string version returned is
+ * independent of the string builder.
+ *
+ * @return the builder as a String
+ */
+ public String toString() {
+ return new String(buffer, 0, size);
+ }
+
+ /**
+ * Gets a StringBuffer version of the string builder, creating a
+ * new instance each time the method is called.
+ *
+ * @return the builder as a StringBuffer
+ */
+ public StringBuffer toStringBuffer() {
+ return new StringBuffer(size).append(buffer, 0, size);
+ }
+
+ /**
+ * Clone this object.
+ *
+ * @return a clone of this object
+ * @throws CloneNotSupportedException if clone is not supported
+ * @since 2.6
+ */
+ public Object clone() throws CloneNotSupportedException {
+ StrBuilder clone = (StrBuilder)super.clone();
+ clone.buffer = new char[buffer.length];
+ System.arraycopy(buffer, 0, clone.buffer, 0, buffer.length);
+ return clone;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Validates parameters defining a range of the builder.
+ *
+ * @param startIndex the start index, inclusive, must be valid
+ * @param endIndex the end index, exclusive, must be valid except
+ * that if too large it is treated as end of string
+ * @return the new string
+ * @throws IndexOutOfBoundsException if the index is invalid
+ */
+ protected int validateRange(int startIndex, int endIndex) {
+ if (startIndex < 0) {
+ throw new StringIndexOutOfBoundsException(startIndex);
+ }
+ if (endIndex > size) {
+ endIndex = size;
+ }
+ if (startIndex > endIndex) {
+ throw new StringIndexOutOfBoundsException("end < start");
+ }
+ return endIndex;
+ }
+
+ /**
+ * Validates parameters defining a single index in the builder.
+ *
+ * @param index the index, must be valid
+ * @throws IndexOutOfBoundsException if the index is invalid
+ */
+ protected void validateIndex(int index) {
+ if (index < 0 || index > size) {
+ throw new StringIndexOutOfBoundsException(index);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Inner class to allow StrBuilder to operate as a tokenizer.
+ */
+ class StrBuilderTokenizer extends StrTokenizer {
+
+ /**
+ * Default constructor.
+ */
+ StrBuilderTokenizer() {
+ super();
+ }
+
+ /** {@inheritDoc} */
+ protected List tokenize(char[] chars, int offset, int count) {
+ if (chars == null) {
+ return super.tokenize(StrBuilder.this.buffer, 0, StrBuilder.this.size());
+ } else {
+ return super.tokenize(chars, offset, count);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public String getContent() {
+ String str = super.getContent();
+ if (str == null) {
+ return StrBuilder.this.toString();
+ } else {
+ return str;
+ }
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Inner class to allow StrBuilder to operate as a writer.
+ */
+ class StrBuilderReader extends Reader {
+ /** The current stream position. */
+ private int pos;
+ /** The last mark position. */
+ private int mark;
+
+ /**
+ * Default constructor.
+ */
+ StrBuilderReader() {
+ super();
+ }
+
+ /** {@inheritDoc} */
+ public void close() {
+ // do nothing
+ }
+
+ /** {@inheritDoc} */
+ public int read() {
+ if (ready() == false) {
+ return -1;
+ }
+ return StrBuilder.this.charAt(pos++);
+ }
+
+ /** {@inheritDoc} */
+ public int read(char b[], int off, int len) {
+ if (off < 0 || len < 0 || off > b.length ||
+ (off + len) > b.length || (off + len) < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (len == 0) {
+ return 0;
+ }
+ if (pos >= StrBuilder.this.size()) {
+ return -1;
+ }
+ if (pos + len > size()) {
+ len = StrBuilder.this.size() - pos;
+ }
+ StrBuilder.this.getChars(pos, pos + len, b, off);
+ pos += len;
+ return len;
+ }
+
+ /** {@inheritDoc} */
+ public long skip(long n) {
+ if (pos + n > StrBuilder.this.size()) {
+ n = StrBuilder.this.size() - pos;
+ }
+ if (n < 0) {
+ return 0;
+ }
+ pos += n;
+ return n;
+ }
+
+ /** {@inheritDoc} */
+ public boolean ready() {
+ return pos < StrBuilder.this.size();
+ }
+
+ /** {@inheritDoc} */
+ public boolean markSupported() {
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ public void mark(int readAheadLimit) {
+ mark = pos;
+ }
+
+ /** {@inheritDoc} */
+ public void reset() {
+ pos = mark;
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Inner class to allow StrBuilder to operate as a writer.
+ */
+ class StrBuilderWriter extends Writer {
+
+ /**
+ * Default constructor.
+ */
+ StrBuilderWriter() {
+ super();
+ }
+
+ /** {@inheritDoc} */
+ public void close() {
+ // do nothing
+ }
+
+ /** {@inheritDoc} */
+ public void flush() {
+ // do nothing
+ }
+
+ /** {@inheritDoc} */
+ public void write(int c) {
+ StrBuilder.this.append((char) c);
+ }
+
+ /** {@inheritDoc} */
+ public void write(char[] cbuf) {
+ StrBuilder.this.append(cbuf);
+ }
+
+ /** {@inheritDoc} */
+ public void write(char[] cbuf, int off, int len) {
+ StrBuilder.this.append(cbuf, off, len);
+ }
+
+ /** {@inheritDoc} */
+ public void write(String str) {
+ StrBuilder.this.append(str);
+ }
+
+ /** {@inheritDoc} */
+ public void write(String str, int off, int len) {
+ StrBuilder.this.append(str, off, len);
+ }
+ }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/text/StrLookup.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/text/StrLookup.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/text/StrLookup.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang.text;
+
+import java.util.Map;
+
+/**
+ * Lookup a String key to a String value.
+ *
+ * This class represents the simplest form of a string to string map.
+ * It has a benefit over a map in that it can create the result on
+ * demand based on the key.
+ *
+ * This class comes complete with various factory methods.
+ * If these do not suffice, you can subclass and implement your own matcher.
+ *
+ * For example, it would be possible to implement a lookup that used the
+ * key as a primary key, and looked up the value on demand from the database
+ *
+ * @author Apache Software Foundation
+ * @since 2.2
+ * @version $Id$
+ */
+public abstract class StrLookup {
+
+ /**
+ * Lookup that always returns null.
+ */
+ private static final StrLookup NONE_LOOKUP;
+ /**
+ * Lookup that uses System properties.
+ */
+ private static final StrLookup SYSTEM_PROPERTIES_LOOKUP;
+ static {
+ NONE_LOOKUP = new MapStrLookup(null);
+ StrLookup lookup = null;
+ try {
+ lookup = new MapStrLookup(System.getProperties());
+ } catch (SecurityException ex) {
+ lookup = NONE_LOOKUP;
+ }
+ SYSTEM_PROPERTIES_LOOKUP = lookup;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Returns a lookup which always returns null.
+ *
+ * @return a lookup that always returns null, not null
+ */
+ public static StrLookup noneLookup() {
+ return NONE_LOOKUP;
+ }
+
+ /**
+ * Returns a lookup which uses {@link System#getProperties() System properties}
+ * to lookup the key to value.
+ *
+ * If a security manager blocked access to system properties, then null will
+ * be returned from every lookup.
+ *
+ * If a null key is used, this lookup will throw a NullPointerException.
+ *
+ * @return a lookup using system properties, not null
+ */
+ public static StrLookup systemPropertiesLookup() {
+ return SYSTEM_PROPERTIES_LOOKUP;
+ }
+
+ /**
+ * Returns a lookup which looks up values using a map.
+ *
+ * If the map is null, then null will be returned from every lookup.
+ * The map result object is converted to a string using toString().
+ *
+ * @param map the map of keys to values, may be null
+ * @return a lookup using the map, not null
+ */
+ public static StrLookup mapLookup(Map map) {
+ return new MapStrLookup(map);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Constructor.
+ */
+ protected StrLookup() {
+ super();
+ }
+
+ /**
+ * Looks up a String key to a String value.
+ *
+ * The internal implementation may use any mechanism to return the value.
+ * The simplest implementation is to use a Map. However, virtually any
+ * implementation is possible.
+ *
+ * For example, it would be possible to implement a lookup that used the
+ * key as a primary key, and looked up the value on demand from the database
+ * Or, a numeric based implementation could be created that treats the key
+ * as an integer, increments the value and return the result as a string -
+ * converting 1 to 2, 15 to 16 etc.
+ *
+ * The {@link #lookup(String)} method always returns a String, regardless of
+ * the underlying data, by converting it as necessary. For example:
+ *
+ * Map map = new HashMap();
+ * map.put("number", new Integer(2));
+ * assertEquals("2", StrLookup.mapLookup(map).lookup("number"));
+ *
+ * @param key the key to be looked up, may be null
+ * @return the matching value, null if no match
+ */
+ public abstract String lookup(String key);
+
+ //-----------------------------------------------------------------------
+ /**
+ * Lookup implementation that uses a Map.
+ */
+ static class MapStrLookup extends StrLookup {
+
+ /** Map keys are variable names and value. */
+ private final Map map;
+
+ /**
+ * Creates a new instance backed by a Map.
+ *
+ * @param map the map of keys to values, may be null
+ */
+ MapStrLookup(Map map) {
+ this.map = map;
+ }
+
+ /**
+ * Looks up a String key to a String value using the map.
+ *
+ * If the map is null, then null is returned.
+ * The map result object is converted to a string using toString().
+ *
+ * @param key the key to be looked up, may be null
+ * @return the matching value, null if no match
+ */
+ public String lookup(String key) {
+ if (map == null) {
+ return null;
+ }
+ Object obj = map.get(key);
+ if (obj == null) {
+ return null;
+ }
+ return obj.toString();
+ }
+ }
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/text/StrMatcher.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/text/StrMatcher.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/text/StrMatcher.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,430 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang.text;
+
+import java.util.Arrays;
+
+/**
+ * A matcher class that can be queried to determine if a character array
+ * portion matches.
+ *
+ * This class comes complete with various factory methods.
+ * If these do not suffice, you can subclass and implement your own matcher.
+ *
+ * @author Apache Software Foundation
+ * @since 2.2
+ * @version $Id$
+ */
+public abstract class StrMatcher {
+
+ /**
+ * Matches the comma character.
+ */
+ private static final StrMatcher COMMA_MATCHER = new CharMatcher(',');
+ /**
+ * Matches the tab character.
+ */
+ private static final StrMatcher TAB_MATCHER = new CharMatcher('\t');
+ /**
+ * Matches the space character.
+ */
+ private static final StrMatcher SPACE_MATCHER = new CharMatcher(' ');
+ /**
+ * Matches the same characters as StringTokenizer,
+ * namely space, tab, newline, formfeed.
+ */
+ private static final StrMatcher SPLIT_MATCHER = new CharSetMatcher(" \t\n\r\f".toCharArray());
+ /**
+ * Matches the String trim() whitespace characters.
+ */
+ private static final StrMatcher TRIM_MATCHER = new TrimMatcher();
+ /**
+ * Matches the double quote character.
+ */
+ private static final StrMatcher SINGLE_QUOTE_MATCHER = new CharMatcher('\'');
+ /**
+ * Matches the double quote character.
+ */
+ private static final StrMatcher DOUBLE_QUOTE_MATCHER = new CharMatcher('"');
+ /**
+ * Matches the single or double quote character.
+ */
+ private static final StrMatcher QUOTE_MATCHER = new CharSetMatcher("'\"".toCharArray());
+ /**
+ * Matches no characters.
+ */
+ private static final StrMatcher NONE_MATCHER = new NoMatcher();
+
+ // -----------------------------------------------------------------------
+
+ /**
+ * Returns a matcher which matches the comma character.
+ *
+ * @return a matcher for a comma
+ */
+ public static StrMatcher commaMatcher() {
+ return COMMA_MATCHER;
+ }
+
+ /**
+ * Returns a matcher which matches the tab character.
+ *
+ * @return a matcher for a tab
+ */
+ public static StrMatcher tabMatcher() {
+ return TAB_MATCHER;
+ }
+
+ /**
+ * Returns a matcher which matches the space character.
+ *
+ * @return a matcher for a space
+ */
+ public static StrMatcher spaceMatcher() {
+ return SPACE_MATCHER;
+ }
+
+ /**
+ * Matches the same characters as StringTokenizer,
+ * namely space, tab, newline and formfeed.
+ *
+ * @return the split matcher
+ */
+ public static StrMatcher splitMatcher() {
+ return SPLIT_MATCHER;
+ }
+
+ /**
+ * Matches the String trim() whitespace characters.
+ *
+ * @return the trim matcher
+ */
+ public static StrMatcher trimMatcher() {
+ return TRIM_MATCHER;
+ }
+
+ /**
+ * Returns a matcher which matches the single quote character.
+ *
+ * @return a matcher for a single quote
+ */
+ public static StrMatcher singleQuoteMatcher() {
+ return SINGLE_QUOTE_MATCHER;
+ }
+
+ /**
+ * Returns a matcher which matches the double quote character.
+ *
+ * @return a matcher for a double quote
+ */
+ public static StrMatcher doubleQuoteMatcher() {
+ return DOUBLE_QUOTE_MATCHER;
+ }
+
+ /**
+ * Returns a matcher which matches the single or double quote character.
+ *
+ * @return a matcher for a single or double quote
+ */
+ public static StrMatcher quoteMatcher() {
+ return QUOTE_MATCHER;
+ }
+
+ /**
+ * Matches no characters.
+ *
+ * @return a matcher that matches nothing
+ */
+ public static StrMatcher noneMatcher() {
+ return NONE_MATCHER;
+ }
+
+ /**
+ * Constructor that creates a matcher from a character.
+ *
+ * @param ch the character to match, must not be null
+ * @return a new Matcher for the given char
+ */
+ public static StrMatcher charMatcher(char ch) {
+ return new CharMatcher(ch);
+ }
+
+ /**
+ * Constructor that creates a matcher from a set of characters.
+ *
+ * @param chars the characters to match, null or empty matches nothing
+ * @return a new matcher for the given char[]
+ */
+ public static StrMatcher charSetMatcher(char[] chars) {
+ if (chars == null || chars.length == 0) {
+ return NONE_MATCHER;
+ }
+ if (chars.length == 1) {
+ return new CharMatcher(chars[0]);
+ }
+ return new CharSetMatcher(chars);
+ }
+
+ /**
+ * Constructor that creates a matcher from a string representing a set of characters.
+ *
+ * @param chars the characters to match, null or empty matches nothing
+ * @return a new Matcher for the given characters
+ */
+ public static StrMatcher charSetMatcher(String chars) {
+ if (chars == null || chars.length() == 0) {
+ return NONE_MATCHER;
+ }
+ if (chars.length() == 1) {
+ return new CharMatcher(chars.charAt(0));
+ }
+ return new CharSetMatcher(chars.toCharArray());
+ }
+
+ /**
+ * Constructor that creates a matcher from a string.
+ *
+ * @param str the string to match, null or empty matches nothing
+ * @return a new Matcher for the given String
+ */
+ public static StrMatcher stringMatcher(String str) {
+ if (str == null || str.length() == 0) {
+ return NONE_MATCHER;
+ }
+ return new StringMatcher(str);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Constructor.
+ */
+ protected StrMatcher() {
+ super();
+ }
+
+ /**
+ * Returns the number of matching characters, zero for no match.
+ *
+ * This method is called to check for a match.
+ * The parameter pos
represents the current position to be
+ * checked in the string buffer
(a character array which must
+ * not be changed).
+ * The API guarantees that pos
is a valid index for buffer
.
+ *
+ * The character array may be larger than the active area to be matched.
+ * Only values in the buffer between the specifed indices may be accessed.
+ *
+ * The matching code may check one character or many.
+ * It may check characters preceeding pos
as well as those
+ * after, so long as no checks exceed the bounds specified.
+ *
+ * It must return zero for no match, or a positive number if a match was found.
+ * The number indicates the number of characters that matched.
+ *
+ * @param buffer the text content to match against, do not change
+ * @param pos the starting position for the match, valid for buffer
+ * @param bufferStart the first active index in the buffer, valid for buffer
+ * @param bufferEnd the end index (exclusive) of the active buffer, valid for buffer
+ * @return the number of matching characters, zero for no match
+ */
+ public abstract int isMatch(char[] buffer, int pos, int bufferStart, int bufferEnd);
+
+ /**
+ * Returns the number of matching characters, zero for no match.
+ *
+ * This method is called to check for a match.
+ * The parameter pos
represents the current position to be
+ * checked in the string buffer
(a character array which must
+ * not be changed).
+ * The API guarantees that pos
is a valid index for buffer
.
+ *
+ * The matching code may check one character or many.
+ * It may check characters preceeding pos
as well as those after.
+ *
+ * It must return zero for no match, or a positive number if a match was found.
+ * The number indicates the number of characters that matched.
+ *
+ * @param buffer the text content to match against, do not change
+ * @param pos the starting position for the match, valid for buffer
+ * @return the number of matching characters, zero for no match
+ * @since 2.4
+ */
+ public int isMatch(char[] buffer, int pos) {
+ return isMatch(buffer, pos, 0, buffer.length);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Class used to define a set of characters for matching purposes.
+ */
+ static final class CharSetMatcher extends StrMatcher {
+ /** The set of characters to match. */
+ private final char[] chars;
+
+ /**
+ * Constructor that creates a matcher from a character array.
+ *
+ * @param chars the characters to match, must not be null
+ */
+ CharSetMatcher(char chars[]) {
+ super();
+ this.chars = (char[]) chars.clone();
+ Arrays.sort(this.chars);
+ }
+
+ /**
+ * Returns whether or not the given character matches.
+ *
+ * @param buffer the text content to match against, do not change
+ * @param pos the starting position for the match, valid for buffer
+ * @param bufferStart the first active index in the buffer, valid for buffer
+ * @param bufferEnd the end index of the active buffer, valid for buffer
+ * @return the number of matching characters, zero for no match
+ */
+ public int isMatch(char[] buffer, int pos, int bufferStart, int bufferEnd) {
+ return Arrays.binarySearch(chars, buffer[pos]) >= 0 ? 1 : 0;
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Class used to define a character for matching purposes.
+ */
+ static final class CharMatcher extends StrMatcher {
+ /** The character to match. */
+ private final char ch;
+
+ /**
+ * Constructor that creates a matcher that matches a single character.
+ *
+ * @param ch the character to match
+ */
+ CharMatcher(char ch) {
+ super();
+ this.ch = ch;
+ }
+
+ /**
+ * Returns whether or not the given character matches.
+ *
+ * @param buffer the text content to match against, do not change
+ * @param pos the starting position for the match, valid for buffer
+ * @param bufferStart the first active index in the buffer, valid for buffer
+ * @param bufferEnd the end index of the active buffer, valid for buffer
+ * @return the number of matching characters, zero for no match
+ */
+ public int isMatch(char[] buffer, int pos, int bufferStart, int bufferEnd) {
+ return ch == buffer[pos] ? 1 : 0;
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Class used to define a set of characters for matching purposes.
+ */
+ static final class StringMatcher extends StrMatcher {
+ /** The string to match, as a character array. */
+ private final char[] chars;
+
+ /**
+ * Constructor that creates a matcher from a String.
+ *
+ * @param str the string to match, must not be null
+ */
+ StringMatcher(String str) {
+ super();
+ chars = str.toCharArray();
+ }
+
+ /**
+ * Returns whether or not the given text matches the stored string.
+ *
+ * @param buffer the text content to match against, do not change
+ * @param pos the starting position for the match, valid for buffer
+ * @param bufferStart the first active index in the buffer, valid for buffer
+ * @param bufferEnd the end index of the active buffer, valid for buffer
+ * @return the number of matching characters, zero for no match
+ */
+ public int isMatch(char[] buffer, int pos, int bufferStart, int bufferEnd) {
+ int len = chars.length;
+ if (pos + len > bufferEnd) {
+ return 0;
+ }
+ for (int i = 0; i < chars.length; i++, pos++) {
+ if (chars[i] != buffer[pos]) {
+ return 0;
+ }
+ }
+ return len;
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Class used to match no characters.
+ */
+ static final class NoMatcher extends StrMatcher {
+
+ /**
+ * Constructs a new instance of NoMatcher
.
+ */
+ NoMatcher() {
+ super();
+ }
+
+ /**
+ * Always returns false
.
+ *
+ * @param buffer the text content to match against, do not change
+ * @param pos the starting position for the match, valid for buffer
+ * @param bufferStart the first active index in the buffer, valid for buffer
+ * @param bufferEnd the end index of the active buffer, valid for buffer
+ * @return the number of matching characters, zero for no match
+ */
+ public int isMatch(char[] buffer, int pos, int bufferStart, int bufferEnd) {
+ return 0;
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Class used to match whitespace as per trim().
+ */
+ static final class TrimMatcher extends StrMatcher {
+
+ /**
+ * Constructs a new instance of TrimMatcher
.
+ */
+ TrimMatcher() {
+ super();
+ }
+
+ /**
+ * Returns whether or not the given character matches.
+ *
+ * @param buffer the text content to match against, do not change
+ * @param pos the starting position for the match, valid for buffer
+ * @param bufferStart the first active index in the buffer, valid for buffer
+ * @param bufferEnd the end index of the active buffer, valid for buffer
+ * @return the number of matching characters, zero for no match
+ */
+ public int isMatch(char[] buffer, int pos, int bufferStart, int bufferEnd) {
+ return buffer[pos] <= 32 ? 1 : 0;
+ }
+ }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/text/StrSubstitutor.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/text/StrSubstitutor.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/text/StrSubstitutor.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,926 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang.text;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * Substitutes variables within a string by values.
+ *
+ * This class takes a piece of text and substitutes all the variables within it.
+ * The default definition of a variable is ${variableName}
.
+ * The prefix and suffix can be changed via constructors and set methods.
+ *
+ * Variable values are typically resolved from a map, but could also be resolved
+ * from system properties, or by supplying a custom variable resolver.
+ *
+ * The simplest example is to use this class to replace Java System properties. For example:
+ *
+ * StrSubstitutor.replaceSystemProperties(
+ * "You are running with java.version = ${java.version} and os.name = ${os.name}.");
+ *
+ *
+ * Typical usage of this class follows the following pattern: First an instance is created
+ * and initialized with the map that contains the values for the available variables.
+ * If a prefix and/or suffix for variables should be used other than the default ones,
+ * the appropriate settings can be performed. After that the replace()
+ * method can be called passing in the source text for interpolation. In the returned
+ * text all variable references (as long as their values are known) will be resolved.
+ * The following example demonstrates this:
+ *
+ * Map valuesMap = HashMap();
+ * valuesMap.put("animal", "quick brown fox");
+ * valuesMap.put("target", "lazy dog");
+ * String templateString = "The ${animal} jumped over the ${target}.";
+ * StrSubstitutor sub = new StrSubstitutor(valuesMap);
+ * String resolvedString = sub.replace(templateString);
+ *
+ * yielding:
+ *
+ * The quick brown fox jumped over the lazy dog.
+ *
+ *
+ * In addition to this usage pattern there are some static convenience methods that
+ * cover the most common use cases. These methods can be used without the need of
+ * manually creating an instance. However if multiple replace operations are to be
+ * performed, creating and reusing an instance of this class will be more efficient.
+ *
+ * Variable replacement works in a recursive way. Thus, if a variable value contains
+ * a variable then that variable will also be replaced. Cyclic replacements are
+ * detected and will cause an exception to be thrown.
+ *
+ * Sometimes the interpolation's result must contain a variable prefix. As an example
+ * take the following source text:
+ *
+ * The variable ${${name}} must be used.
+ *
+ * Here only the variable's name referred to in the text should be replaced resulting
+ * in the text (assuming that the value of the name
variable is x
):
+ *
+ * The variable ${x} must be used.
+ *
+ * To achieve this effect there are two possibilities: Either set a different prefix
+ * and suffix for variables which do not conflict with the result text you want to
+ * produce. The other possibility is to use the escape character, by default '$'.
+ * If this character is placed before a variable reference, this reference is ignored
+ * and won't be replaced. For example:
+ *
+ * The variable $${${name}} must be used.
+ *
+ *
+ * In some complex scenarios you might even want to perform substitution in the
+ * names of variables, for instance
+ *
+ * ${jre-${java.specification.version}}
+ *
+ * StrSubstitutor
supports this recursive substitution in variable
+ * names, but it has to be enabled explicitly by setting the
+ * {@link #setEnableSubstitutionInVariables(boolean) enableSubstitutionInVariables}
+ * property to true.
+ *
+ * @author Apache Software Foundation
+ * @author Oliver Heger
+ * @version $Id$
+ * @since 2.2
+ */
+public class StrSubstitutor {
+
+ /**
+ * Constant for the default escape character.
+ */
+ public static final char DEFAULT_ESCAPE = '$';
+ /**
+ * Constant for the default variable prefix.
+ */
+ public static final StrMatcher DEFAULT_PREFIX = StrMatcher.stringMatcher("${");
+ /**
+ * Constant for the default variable suffix.
+ */
+ public static final StrMatcher DEFAULT_SUFFIX = StrMatcher.stringMatcher("}");
+
+ /**
+ * Stores the escape character.
+ */
+ private char escapeChar;
+ /**
+ * Stores the variable prefix.
+ */
+ private StrMatcher prefixMatcher;
+ /**
+ * Stores the variable suffix.
+ */
+ private StrMatcher suffixMatcher;
+ /**
+ * Variable resolution is delegated to an implementor of VariableResolver.
+ */
+ private StrLookup variableResolver;
+ /**
+ * The flag whether substitution in variable names is enabled.
+ */
+ private boolean enableSubstitutionInVariables;
+
+ //-----------------------------------------------------------------------
+ /**
+ * Replaces all the occurrences of variables in the given source object with
+ * their matching values from the map.
+ *
+ * @param source the source text containing the variables to substitute, null returns null
+ * @param valueMap the map with the values, may be null
+ * @return the result of the replace operation
+ */
+ public static String replace(Object source, Map valueMap) {
+ return new StrSubstitutor(valueMap).replace(source);
+ }
+
+ /**
+ * Replaces all the occurrences of variables in the given source object with
+ * their matching values from the map. This method allows to specifiy a
+ * custom variable prefix and suffix
+ *
+ * @param source the source text containing the variables to substitute, null returns null
+ * @param valueMap the map with the values, may be null
+ * @param prefix the prefix of variables, not null
+ * @param suffix the suffix of variables, not null
+ * @return the result of the replace operation
+ * @throws IllegalArgumentException if the prefix or suffix is null
+ */
+ public static String replace(Object source, Map valueMap, String prefix, String suffix) {
+ return new StrSubstitutor(valueMap, prefix, suffix).replace(source);
+ }
+
+ /**
+ * Replaces all the occurrences of variables in the given source object with their matching
+ * values from the properties.
+ *
+ * @param source the source text containing the variables to substitute, null returns null
+ * @param valueProperties the properties with values, may be null
+ * @return the result of the replace operation
+ * @since 2.6
+ */
+ public static String replace(Object source, Properties valueProperties)
+ {
+ if (valueProperties == null) {
+ return source.toString();
+ }
+ Map valueMap = new HashMap();
+ Enumeration propNames = valueProperties.propertyNames();
+ while (propNames.hasMoreElements())
+ {
+ String propName = (String)propNames.nextElement();
+ String propValue = valueProperties.getProperty(propName);
+ valueMap.put(propName, propValue);
+ }
+ return StrSubstitutor.replace(source, valueMap);
+ }
+
+ /**
+ * Replaces all the occurrences of variables in the given source object with
+ * their matching values from the system properties.
+ *
+ * @param source the source text containing the variables to substitute, null returns null
+ * @return the result of the replace operation
+ */
+ public static String replaceSystemProperties(Object source) {
+ return new StrSubstitutor(StrLookup.systemPropertiesLookup()).replace(source);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Creates a new instance with defaults for variable prefix and suffix
+ * and the escaping character.
+ */
+ public StrSubstitutor() {
+ this((StrLookup) null, DEFAULT_PREFIX, DEFAULT_SUFFIX, DEFAULT_ESCAPE);
+ }
+
+ /**
+ * Creates a new instance and initializes it. Uses defaults for variable
+ * prefix and suffix and the escaping character.
+ *
+ * @param valueMap the map with the variables' values, may be null
+ */
+ public StrSubstitutor(Map valueMap) {
+ this(StrLookup.mapLookup(valueMap), DEFAULT_PREFIX, DEFAULT_SUFFIX, DEFAULT_ESCAPE);
+ }
+
+ /**
+ * Creates a new instance and initializes it. Uses a default escaping character.
+ *
+ * @param valueMap the map with the variables' values, may be null
+ * @param prefix the prefix for variables, not null
+ * @param suffix the suffix for variables, not null
+ * @throws IllegalArgumentException if the prefix or suffix is null
+ */
+ public StrSubstitutor(Map valueMap, String prefix, String suffix) {
+ this(StrLookup.mapLookup(valueMap), prefix, suffix, DEFAULT_ESCAPE);
+ }
+
+ /**
+ * Creates a new instance and initializes it.
+ *
+ * @param valueMap the map with the variables' values, may be null
+ * @param prefix the prefix for variables, not null
+ * @param suffix the suffix for variables, not null
+ * @param escape the escape character
+ * @throws IllegalArgumentException if the prefix or suffix is null
+ */
+ public StrSubstitutor(Map valueMap, String prefix, String suffix, char escape) {
+ this(StrLookup.mapLookup(valueMap), prefix, suffix, escape);
+ }
+
+ /**
+ * Creates a new instance and initializes it.
+ *
+ * @param variableResolver the variable resolver, may be null
+ */
+ public StrSubstitutor(StrLookup variableResolver) {
+ this(variableResolver, DEFAULT_PREFIX, DEFAULT_SUFFIX, DEFAULT_ESCAPE);
+ }
+
+ /**
+ * Creates a new instance and initializes it.
+ *
+ * @param variableResolver the variable resolver, may be null
+ * @param prefix the prefix for variables, not null
+ * @param suffix the suffix for variables, not null
+ * @param escape the escape character
+ * @throws IllegalArgumentException if the prefix or suffix is null
+ */
+ public StrSubstitutor(StrLookup variableResolver, String prefix, String suffix, char escape) {
+ this.setVariableResolver(variableResolver);
+ this.setVariablePrefix(prefix);
+ this.setVariableSuffix(suffix);
+ this.setEscapeChar(escape);
+ }
+
+ /**
+ * Creates a new instance and initializes it.
+ *
+ * @param variableResolver the variable resolver, may be null
+ * @param prefixMatcher the prefix for variables, not null
+ * @param suffixMatcher the suffix for variables, not null
+ * @param escape the escape character
+ * @throws IllegalArgumentException if the prefix or suffix is null
+ */
+ public StrSubstitutor(
+ StrLookup variableResolver, StrMatcher prefixMatcher, StrMatcher suffixMatcher, char escape) {
+ this.setVariableResolver(variableResolver);
+ this.setVariablePrefixMatcher(prefixMatcher);
+ this.setVariableSuffixMatcher(suffixMatcher);
+ this.setEscapeChar(escape);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Replaces all the occurrences of variables with their matching values
+ * from the resolver using the given source string as a template.
+ *
+ * @param source the string to replace in, null returns null
+ * @return the result of the replace operation
+ */
+ public String replace(String source) {
+ if (source == null) {
+ return null;
+ }
+ StrBuilder buf = new StrBuilder(source);
+ if (substitute(buf, 0, source.length()) == false) {
+ return source;
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Replaces all the occurrences of variables with their matching values
+ * from the resolver using the given source string as a template.
+ *
+ * Only the specified portion of the string will be processed.
+ * The rest of the string is not processed, and is not returned.
+ *
+ * @param source the string to replace in, null returns null
+ * @param offset the start offset within the array, must be valid
+ * @param length the length within the array to be processed, must be valid
+ * @return the result of the replace operation
+ */
+ public String replace(String source, int offset, int length) {
+ if (source == null) {
+ return null;
+ }
+ StrBuilder buf = new StrBuilder(length).append(source, offset, length);
+ if (substitute(buf, 0, length) == false) {
+ return source.substring(offset, offset + length);
+ }
+ return buf.toString();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Replaces all the occurrences of variables with their matching values
+ * from the resolver using the given source array as a template.
+ * The array is not altered by this method.
+ *
+ * @param source the character array to replace in, not altered, null returns null
+ * @return the result of the replace operation
+ */
+ public String replace(char[] source) {
+ if (source == null) {
+ return null;
+ }
+ StrBuilder buf = new StrBuilder(source.length).append(source);
+ substitute(buf, 0, source.length);
+ return buf.toString();
+ }
+
+ /**
+ * Replaces all the occurrences of variables with their matching values
+ * from the resolver using the given source array as a template.
+ * The array is not altered by this method.
+ *
+ * Only the specified portion of the array will be processed.
+ * The rest of the array is not processed, and is not returned.
+ *
+ * @param source the character array to replace in, not altered, null returns null
+ * @param offset the start offset within the array, must be valid
+ * @param length the length within the array to be processed, must be valid
+ * @return the result of the replace operation
+ */
+ public String replace(char[] source, int offset, int length) {
+ if (source == null) {
+ return null;
+ }
+ StrBuilder buf = new StrBuilder(length).append(source, offset, length);
+ substitute(buf, 0, length);
+ return buf.toString();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Replaces all the occurrences of variables with their matching values
+ * from the resolver using the given source buffer as a template.
+ * The buffer is not altered by this method.
+ *
+ * @param source the buffer to use as a template, not changed, null returns null
+ * @return the result of the replace operation
+ */
+ public String replace(StringBuffer source) {
+ if (source == null) {
+ return null;
+ }
+ StrBuilder buf = new StrBuilder(source.length()).append(source);
+ substitute(buf, 0, buf.length());
+ return buf.toString();
+ }
+
+ /**
+ * Replaces all the occurrences of variables with their matching values
+ * from the resolver using the given source buffer as a template.
+ * The buffer is not altered by this method.
+ *
+ * Only the specified portion of the buffer will be processed.
+ * The rest of the buffer is not processed, and is not returned.
+ *
+ * @param source the buffer to use as a template, not changed, null returns null
+ * @param offset the start offset within the array, must be valid
+ * @param length the length within the array to be processed, must be valid
+ * @return the result of the replace operation
+ */
+ public String replace(StringBuffer source, int offset, int length) {
+ if (source == null) {
+ return null;
+ }
+ StrBuilder buf = new StrBuilder(length).append(source, offset, length);
+ substitute(buf, 0, length);
+ return buf.toString();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Replaces all the occurrences of variables with their matching values
+ * from the resolver using the given source builder as a template.
+ * The builder is not altered by this method.
+ *
+ * @param source the builder to use as a template, not changed, null returns null
+ * @return the result of the replace operation
+ */
+ public String replace(StrBuilder source) {
+ if (source == null) {
+ return null;
+ }
+ StrBuilder buf = new StrBuilder(source.length()).append(source);
+ substitute(buf, 0, buf.length());
+ return buf.toString();
+ }
+
+ /**
+ * Replaces all the occurrences of variables with their matching values
+ * from the resolver using the given source builder as a template.
+ * The builder is not altered by this method.
+ *
+ * Only the specified portion of the builder will be processed.
+ * The rest of the builder is not processed, and is not returned.
+ *
+ * @param source the builder to use as a template, not changed, null returns null
+ * @param offset the start offset within the array, must be valid
+ * @param length the length within the array to be processed, must be valid
+ * @return the result of the replace operation
+ */
+ public String replace(StrBuilder source, int offset, int length) {
+ if (source == null) {
+ return null;
+ }
+ StrBuilder buf = new StrBuilder(length).append(source, offset, length);
+ substitute(buf, 0, length);
+ return buf.toString();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Replaces all the occurrences of variables in the given source object with
+ * their matching values from the resolver. The input source object is
+ * converted to a string using toString
and is not altered.
+ *
+ * @param source the source to replace in, null returns null
+ * @return the result of the replace operation
+ */
+ public String replace(Object source) {
+ if (source == null) {
+ return null;
+ }
+ StrBuilder buf = new StrBuilder().append(source);
+ substitute(buf, 0, buf.length());
+ return buf.toString();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Replaces all the occurrences of variables within the given source buffer
+ * with their matching values from the resolver.
+ * The buffer is updated with the result.
+ *
+ * @param source the buffer to replace in, updated, null returns zero
+ * @return true if altered
+ */
+ public boolean replaceIn(StringBuffer source) {
+ if (source == null) {
+ return false;
+ }
+ return replaceIn(source, 0, source.length());
+ }
+
+ /**
+ * Replaces all the occurrences of variables within the given source buffer
+ * with their matching values from the resolver.
+ * The buffer is updated with the result.
+ *
+ * Only the specified portion of the buffer will be processed.
+ * The rest of the buffer is not processed, but it is not deleted.
+ *
+ * @param source the buffer to replace in, updated, null returns zero
+ * @param offset the start offset within the array, must be valid
+ * @param length the length within the buffer to be processed, must be valid
+ * @return true if altered
+ */
+ public boolean replaceIn(StringBuffer source, int offset, int length) {
+ if (source == null) {
+ return false;
+ }
+ StrBuilder buf = new StrBuilder(length).append(source, offset, length);
+ if (substitute(buf, 0, length) == false) {
+ return false;
+ }
+ source.replace(offset, offset + length, buf.toString());
+ return true;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Replaces all the occurrences of variables within the given source
+ * builder with their matching values from the resolver.
+ *
+ * @param source the builder to replace in, updated, null returns zero
+ * @return true if altered
+ */
+ public boolean replaceIn(StrBuilder source) {
+ if (source == null) {
+ return false;
+ }
+ return substitute(source, 0, source.length());
+ }
+
+ /**
+ * Replaces all the occurrences of variables within the given source
+ * builder with their matching values from the resolver.
+ *
+ * Only the specified portion of the builder will be processed.
+ * The rest of the builder is not processed, but it is not deleted.
+ *
+ * @param source the builder to replace in, null returns zero
+ * @param offset the start offset within the array, must be valid
+ * @param length the length within the builder to be processed, must be valid
+ * @return true if altered
+ */
+ public boolean replaceIn(StrBuilder source, int offset, int length) {
+ if (source == null) {
+ return false;
+ }
+ return substitute(source, offset, length);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Internal method that substitutes the variables.
+ *
+ * Most users of this class do not need to call this method. This method will
+ * be called automatically by another (public) method.
+ *
+ * Writers of subclasses can override this method if they need access to
+ * the substitution process at the start or end.
+ *
+ * @param buf the string builder to substitute into, not null
+ * @param offset the start offset within the builder, must be valid
+ * @param length the length within the builder to be processed, must be valid
+ * @return true if altered
+ */
+ protected boolean substitute(StrBuilder buf, int offset, int length) {
+ return substitute(buf, offset, length, null) > 0;
+ }
+
+ /**
+ * Recursive handler for multiple levels of interpolation. This is the main
+ * interpolation method, which resolves the values of all variable references
+ * contained in the passed in text.
+ *
+ * @param buf the string builder to substitute into, not null
+ * @param offset the start offset within the builder, must be valid
+ * @param length the length within the builder to be processed, must be valid
+ * @param priorVariables the stack keeping track of the replaced variables, may be null
+ * @return the length change that occurs, unless priorVariables is null when the int
+ * represents a boolean flag as to whether any change occurred.
+ */
+ private int substitute(StrBuilder buf, int offset, int length, List priorVariables) {
+ StrMatcher prefixMatcher = getVariablePrefixMatcher();
+ StrMatcher suffixMatcher = getVariableSuffixMatcher();
+ char escape = getEscapeChar();
+
+ boolean top = (priorVariables == null);
+ boolean altered = false;
+ int lengthChange = 0;
+ char[] chars = buf.buffer;
+ int bufEnd = offset + length;
+ int pos = offset;
+ while (pos < bufEnd) {
+ int startMatchLen = prefixMatcher.isMatch(chars, pos, offset,
+ bufEnd);
+ if (startMatchLen == 0) {
+ pos++;
+ } else {
+ // found variable start marker
+ if (pos > offset && chars[pos - 1] == escape) {
+ // escaped
+ buf.deleteCharAt(pos - 1);
+ chars = buf.buffer; // in case buffer was altered
+ lengthChange--;
+ altered = true;
+ bufEnd--;
+ } else {
+ // find suffix
+ int startPos = pos;
+ pos += startMatchLen;
+ int endMatchLen = 0;
+ int nestedVarCount = 0;
+ while (pos < bufEnd) {
+ if (isEnableSubstitutionInVariables()
+ && (endMatchLen = prefixMatcher.isMatch(chars,
+ pos, offset, bufEnd)) != 0) {
+ // found a nested variable start
+ nestedVarCount++;
+ pos += endMatchLen;
+ continue;
+ }
+
+ endMatchLen = suffixMatcher.isMatch(chars, pos, offset,
+ bufEnd);
+ if (endMatchLen == 0) {
+ pos++;
+ } else {
+ // found variable end marker
+ if (nestedVarCount == 0) {
+ String varName = new String(chars, startPos
+ + startMatchLen, pos - startPos
+ - startMatchLen);
+ if (isEnableSubstitutionInVariables()) {
+ StrBuilder bufName = new StrBuilder(varName);
+ substitute(bufName, 0, bufName.length());
+ varName = bufName.toString();
+ }
+ pos += endMatchLen;
+ int endPos = pos;
+
+ // on the first call initialize priorVariables
+ if (priorVariables == null) {
+ priorVariables = new ArrayList();
+ priorVariables.add(new String(chars,
+ offset, length));
+ }
+
+ // handle cyclic substitution
+ checkCyclicSubstitution(varName, priorVariables);
+ priorVariables.add(varName);
+
+ // resolve the variable
+ String varValue = resolveVariable(varName, buf,
+ startPos, endPos);
+ if (varValue != null) {
+ // recursive replace
+ int varLen = varValue.length();
+ buf.replace(startPos, endPos, varValue);
+ altered = true;
+ int change = substitute(buf, startPos,
+ varLen, priorVariables);
+ change = change
+ + (varLen - (endPos - startPos));
+ pos += change;
+ bufEnd += change;
+ lengthChange += change;
+ chars = buf.buffer; // in case buffer was
+ // altered
+ }
+
+ // remove variable from the cyclic stack
+ priorVariables
+ .remove(priorVariables.size() - 1);
+ break;
+ } else {
+ nestedVarCount--;
+ pos += endMatchLen;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (top) {
+ return (altered ? 1 : 0);
+ }
+ return lengthChange;
+ }
+
+ /**
+ * Checks if the specified variable is already in the stack (list) of variables.
+ *
+ * @param varName the variable name to check
+ * @param priorVariables the list of prior variables
+ */
+ private void checkCyclicSubstitution(String varName, List priorVariables) {
+ if (priorVariables.contains(varName) == false) {
+ return;
+ }
+ StrBuilder buf = new StrBuilder(256);
+ buf.append("Infinite loop in property interpolation of ");
+ buf.append(priorVariables.remove(0));
+ buf.append(": ");
+ buf.appendWithSeparators(priorVariables, "->");
+ throw new IllegalStateException(buf.toString());
+ }
+
+ /**
+ * Internal method that resolves the value of a variable.
+ *
+ * Most users of this class do not need to call this method. This method is
+ * called automatically by the substitution process.
+ *
+ * Writers of subclasses can override this method if they need to alter
+ * how each substitution occurs. The method is passed the variable's name
+ * and must return the corresponding value. This implementation uses the
+ * {@link #getVariableResolver()} with the variable's name as the key.
+ *
+ * @param variableName the name of the variable, not null
+ * @param buf the buffer where the substitution is occurring, not null
+ * @param startPos the start position of the variable including the prefix, valid
+ * @param endPos the end position of the variable including the suffix, valid
+ * @return the variable's value or null if the variable is unknown
+ */
+ protected String resolveVariable(String variableName, StrBuilder buf, int startPos, int endPos) {
+ StrLookup resolver = getVariableResolver();
+ if (resolver == null) {
+ return null;
+ }
+ return resolver.lookup(variableName);
+ }
+
+ // Escape
+ //-----------------------------------------------------------------------
+ /**
+ * Returns the escape character.
+ *
+ * @return the character used for escaping variable references
+ */
+ public char getEscapeChar() {
+ return this.escapeChar;
+ }
+
+ /**
+ * Sets the escape character.
+ * If this character is placed before a variable reference in the source
+ * text, this variable will be ignored.
+ *
+ * @param escapeCharacter the escape character (0 for disabling escaping)
+ */
+ public void setEscapeChar(char escapeCharacter) {
+ this.escapeChar = escapeCharacter;
+ }
+
+ // Prefix
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the variable prefix matcher currently in use.
+ *
+ * The variable prefix is the characer or characters that identify the
+ * start of a variable. This prefix is expressed in terms of a matcher
+ * allowing advanced prefix matches.
+ *
+ * @return the prefix matcher in use
+ */
+ public StrMatcher getVariablePrefixMatcher() {
+ return prefixMatcher;
+ }
+
+ /**
+ * Sets the variable prefix matcher currently in use.
+ *
+ * The variable prefix is the characer or characters that identify the
+ * start of a variable. This prefix is expressed in terms of a matcher
+ * allowing advanced prefix matches.
+ *
+ * @param prefixMatcher the prefix matcher to use, null ignored
+ * @return this, to enable chaining
+ * @throws IllegalArgumentException if the prefix matcher is null
+ */
+ public StrSubstitutor setVariablePrefixMatcher(StrMatcher prefixMatcher) {
+ if (prefixMatcher == null) {
+ throw new IllegalArgumentException("Variable prefix matcher must not be null!");
+ }
+ this.prefixMatcher = prefixMatcher;
+ return this;
+ }
+
+ /**
+ * Sets the variable prefix to use.
+ *
+ * The variable prefix is the character or characters that identify the
+ * start of a variable. This method allows a single character prefix to
+ * be easily set.
+ *
+ * @param prefix the prefix character to use
+ * @return this, to enable chaining
+ */
+ public StrSubstitutor setVariablePrefix(char prefix) {
+ return setVariablePrefixMatcher(StrMatcher.charMatcher(prefix));
+ }
+
+ /**
+ * Sets the variable prefix to use.
+ *
+ * The variable prefix is the characer or characters that identify the
+ * start of a variable. This method allows a string prefix to be easily set.
+ *
+ * @param prefix the prefix for variables, not null
+ * @return this, to enable chaining
+ * @throws IllegalArgumentException if the prefix is null
+ */
+ public StrSubstitutor setVariablePrefix(String prefix) {
+ if (prefix == null) {
+ throw new IllegalArgumentException("Variable prefix must not be null!");
+ }
+ return setVariablePrefixMatcher(StrMatcher.stringMatcher(prefix));
+ }
+
+ // Suffix
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the variable suffix matcher currently in use.
+ *
+ * The variable suffix is the characer or characters that identify the
+ * end of a variable. This suffix is expressed in terms of a matcher
+ * allowing advanced suffix matches.
+ *
+ * @return the suffix matcher in use
+ */
+ public StrMatcher getVariableSuffixMatcher() {
+ return suffixMatcher;
+ }
+
+ /**
+ * Sets the variable suffix matcher currently in use.
+ *
+ * The variable suffix is the characer or characters that identify the
+ * end of a variable. This suffix is expressed in terms of a matcher
+ * allowing advanced suffix matches.
+ *
+ * @param suffixMatcher the suffix matcher to use, null ignored
+ * @return this, to enable chaining
+ * @throws IllegalArgumentException if the suffix matcher is null
+ */
+ public StrSubstitutor setVariableSuffixMatcher(StrMatcher suffixMatcher) {
+ if (suffixMatcher == null) {
+ throw new IllegalArgumentException("Variable suffix matcher must not be null!");
+ }
+ this.suffixMatcher = suffixMatcher;
+ return this;
+ }
+
+ /**
+ * Sets the variable suffix to use.
+ *
+ * The variable suffix is the characer or characters that identify the
+ * end of a variable. This method allows a single character suffix to
+ * be easily set.
+ *
+ * @param suffix the suffix character to use
+ * @return this, to enable chaining
+ */
+ public StrSubstitutor setVariableSuffix(char suffix) {
+ return setVariableSuffixMatcher(StrMatcher.charMatcher(suffix));
+ }
+
+ /**
+ * Sets the variable suffix to use.
+ *
+ * The variable suffix is the character or characters that identify the
+ * end of a variable. This method allows a string suffix to be easily set.
+ *
+ * @param suffix the suffix for variables, not null
+ * @return this, to enable chaining
+ * @throws IllegalArgumentException if the suffix is null
+ */
+ public StrSubstitutor setVariableSuffix(String suffix) {
+ if (suffix == null) {
+ throw new IllegalArgumentException("Variable suffix must not be null!");
+ }
+ return setVariableSuffixMatcher(StrMatcher.stringMatcher(suffix));
+ }
+
+ // Resolver
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the VariableResolver that is used to lookup variables.
+ *
+ * @return the VariableResolver
+ */
+ public StrLookup getVariableResolver() {
+ return this.variableResolver;
+ }
+
+ /**
+ * Sets the VariableResolver that is used to lookup variables.
+ *
+ * @param variableResolver the VariableResolver
+ */
+ public void setVariableResolver(StrLookup variableResolver) {
+ this.variableResolver = variableResolver;
+ }
+
+ // Substitution support in variable names
+ //-----------------------------------------------------------------------
+ /**
+ * Returns a flag whether substitution is done in variable names.
+ *
+ * @return the substitution in variable names flag
+ * @since 2.6
+ */
+ public boolean isEnableSubstitutionInVariables() {
+ return enableSubstitutionInVariables;
+ }
+
+ /**
+ * Sets a flag whether substitution is done in variable names. If set to
+ * true, the names of variables can contain other variables which are
+ * processed first before the original variable is evaluated, e.g.
+ * ${jre-${java.version}}
. The default value is false.
+ *
+ * @param enableSubstitutionInVariables the new value of the flag
+ * @since 2.6
+ */
+ public void setEnableSubstitutionInVariables(
+ boolean enableSubstitutionInVariables) {
+ this.enableSubstitutionInVariables = enableSubstitutionInVariables;
+ }
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/text/StrTokenizer.java
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/text/StrTokenizer.java (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/text/StrTokenizer.java (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,1127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.lang.text;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+/**
+ * Tokenizes a string based based on delimiters (separators)
+ * and supporting quoting and ignored character concepts.
+ *
+ * This class can split a String into many smaller strings. It aims
+ * to do a similar job to {@link java.util.StringTokenizer StringTokenizer},
+ * however it offers much more control and flexibility including implementing
+ * the ListIterator
interface. By default, it is set up
+ * like StringTokenizer
.
+ *
+ * The input String is split into a number of tokens.
+ * Each token is separated from the next String by a delimiter.
+ * One or more delimiter characters must be specified.
+ *
+ * Each token may be surrounded by quotes.
+ * The quote matcher specifies the quote character(s).
+ * A quote may be escaped within a quoted section by duplicating itself.
+ *
+ * Between each token and the delimiter are potentially characters that need trimming.
+ * The trimmer matcher specifies these characters.
+ * One usage might be to trim whitespace characters.
+ *
+ * At any point outside the quotes there might potentially be invalid characters.
+ * The ignored matcher specifies these characters to be removed.
+ * One usage might be to remove new line characters.
+ *
+ * Empty tokens may be removed or returned as null.
+ *
+ * "a,b,c" - Three tokens "a","b","c" (comma delimiter)
+ * " a, b , c " - Three tokens "a","b","c" (default CSV processing trims whitespace)
+ * "a, ", b ,", c" - Three tokens "a, " , " b ", ", c" (quoted text untouched)
+ *
+ *
+ *
+ * This tokenizer has the following properties and options:
+ *
+ *
+ *
+ * Property Type Default
+ *
+ *
+ * delim CharSetMatcher { \t\n\r\f}
+ *
+ *
+ * quote NoneMatcher {}
+ *
+ *
+ * ignore NoneMatcher {}
+ *
+ *
+ * emptyTokenAsNull boolean false
+ *
+ *
+ * ignoreEmptyTokens boolean true
+ *
+ *
+ *
+ * @author Apache Software Foundation
+ * @author Matthew Inger
+ * @author Gary D. Gregory
+ * @since 2.2
+ * @version $Id$
+ */
+public class StrTokenizer implements ListIterator, Cloneable {
+
+ private static final StrTokenizer CSV_TOKENIZER_PROTOTYPE;
+ private static final StrTokenizer TSV_TOKENIZER_PROTOTYPE;
+ static {
+ CSV_TOKENIZER_PROTOTYPE = new StrTokenizer();
+ CSV_TOKENIZER_PROTOTYPE.setDelimiterMatcher(StrMatcher.commaMatcher());
+ CSV_TOKENIZER_PROTOTYPE.setQuoteMatcher(StrMatcher.doubleQuoteMatcher());
+ CSV_TOKENIZER_PROTOTYPE.setIgnoredMatcher(StrMatcher.noneMatcher());
+ CSV_TOKENIZER_PROTOTYPE.setTrimmerMatcher(StrMatcher.trimMatcher());
+ CSV_TOKENIZER_PROTOTYPE.setEmptyTokenAsNull(false);
+ CSV_TOKENIZER_PROTOTYPE.setIgnoreEmptyTokens(false);
+
+ TSV_TOKENIZER_PROTOTYPE = new StrTokenizer();
+ TSV_TOKENIZER_PROTOTYPE.setDelimiterMatcher(StrMatcher.tabMatcher());
+ TSV_TOKENIZER_PROTOTYPE.setQuoteMatcher(StrMatcher.doubleQuoteMatcher());
+ TSV_TOKENIZER_PROTOTYPE.setIgnoredMatcher(StrMatcher.noneMatcher());
+ TSV_TOKENIZER_PROTOTYPE.setTrimmerMatcher(StrMatcher.trimMatcher());
+ TSV_TOKENIZER_PROTOTYPE.setEmptyTokenAsNull(false);
+ TSV_TOKENIZER_PROTOTYPE.setIgnoreEmptyTokens(false);
+ }
+
+ /** The text to work on. */
+ private char chars[];
+ /** The parsed tokens */
+ private String tokens[];
+ /** The current iteration position */
+ private int tokenPos;
+
+ /** The delimiter matcher */
+ private StrMatcher delimMatcher = StrMatcher.splitMatcher();
+ /** The quote matcher */
+ private StrMatcher quoteMatcher = StrMatcher.noneMatcher();
+ /** The ignored matcher */
+ private StrMatcher ignoredMatcher = StrMatcher.noneMatcher();
+ /** The trimmer matcher */
+ private StrMatcher trimmerMatcher = StrMatcher.noneMatcher();
+
+ /** Whether to return empty tokens as null */
+ private boolean emptyAsNull = false;
+ /** Whether to ignore empty tokens */
+ private boolean ignoreEmptyTokens = true;
+
+ //-----------------------------------------------------------------------
+
+ /**
+ * Returns a clone of CSV_TOKENIZER_PROTOTYPE
.
+ *
+ * @return a clone of CSV_TOKENIZER_PROTOTYPE
.
+ */
+ private static StrTokenizer getCSVClone() {
+ return (StrTokenizer) CSV_TOKENIZER_PROTOTYPE.clone();
+ }
+
+ /**
+ * Gets a new tokenizer instance which parses Comma Separated Value strings
+ * initializing it with the given input. The default for CSV processing
+ * will be trim whitespace from both ends (which can be overridden with
+ * the setTrimmer method).
+ *
+ * You must call a "reset" method to set the string which you want to parse.
+ * @return a new tokenizer instance which parses Comma Separated Value strings
+ */
+ public static StrTokenizer getCSVInstance() {
+ return getCSVClone();
+ }
+
+ /**
+ * Gets a new tokenizer instance which parses Comma Separated Value strings
+ * initializing it with the given input. The default for CSV processing
+ * will be trim whitespace from both ends (which can be overridden with
+ * the setTrimmer method).
+ *
+ * @param input the text to parse
+ * @return a new tokenizer instance which parses Comma Separated Value strings
+ */
+ public static StrTokenizer getCSVInstance(String input) {
+ StrTokenizer tok = getCSVClone();
+ tok.reset(input);
+ return tok;
+ }
+
+ /**
+ * Gets a new tokenizer instance which parses Comma Separated Value strings
+ * initializing it with the given input. The default for CSV processing
+ * will be trim whitespace from both ends (which can be overridden with
+ * the setTrimmer method).
+ *
+ * @param input the text to parse
+ * @return a new tokenizer instance which parses Comma Separated Value strings
+ */
+ public static StrTokenizer getCSVInstance(char[] input) {
+ StrTokenizer tok = getCSVClone();
+ tok.reset(input);
+ return tok;
+ }
+
+ /**
+ * Returns a clone of TSV_TOKENIZER_PROTOTYPE
.
+ *
+ * @return a clone of TSV_TOKENIZER_PROTOTYPE
.
+ */
+ private static StrTokenizer getTSVClone() {
+ return (StrTokenizer) TSV_TOKENIZER_PROTOTYPE.clone();
+ }
+
+
+ /**
+ * Gets a new tokenizer instance which parses Tab Separated Value strings.
+ * The default for CSV processing will be trim whitespace from both ends
+ * (which can be overridden with the setTrimmer method).
+ *
+ * You must call a "reset" method to set the string which you want to parse.
+ * @return a new tokenizer instance which parses Tab Separated Value strings.
+ */
+ public static StrTokenizer getTSVInstance() {
+ return getTSVClone();
+ }
+
+ /**
+ * Gets a new tokenizer instance which parses Tab Separated Value strings.
+ * The default for CSV processing will be trim whitespace from both ends
+ * (which can be overridden with the setTrimmer method).
+ * @param input the string to parse
+ * @return a new tokenizer instance which parses Tab Separated Value strings.
+ */
+ public static StrTokenizer getTSVInstance(String input) {
+ StrTokenizer tok = getTSVClone();
+ tok.reset(input);
+ return tok;
+ }
+
+ /**
+ * Gets a new tokenizer instance which parses Tab Separated Value strings.
+ * The default for CSV processing will be trim whitespace from both ends
+ * (which can be overridden with the setTrimmer method).
+ * @param input the string to parse
+ * @return a new tokenizer instance which parses Tab Separated Value strings.
+ */
+ public static StrTokenizer getTSVInstance(char[] input) {
+ StrTokenizer tok = getTSVClone();
+ tok.reset(input);
+ return tok;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Constructs a tokenizer splitting on space, tab, newline and formfeed
+ * as per StringTokenizer, but with no text to tokenize.
+ *
+ * This constructor is normally used with {@link #reset(String)}.
+ */
+ public StrTokenizer() {
+ super();
+ this.chars = null;
+ }
+
+ /**
+ * Constructs a tokenizer splitting on space, tab, newline and formfeed
+ * as per StringTokenizer.
+ *
+ * @param input the string which is to be parsed
+ */
+ public StrTokenizer(String input) {
+ super();
+ if (input != null) {
+ chars = input.toCharArray();
+ } else {
+ chars = null;
+ }
+ }
+
+ /**
+ * Constructs a tokenizer splitting on the specified delimiter character.
+ *
+ * @param input the string which is to be parsed
+ * @param delim the field delimiter character
+ */
+ public StrTokenizer(String input, char delim) {
+ this(input);
+ setDelimiterChar(delim);
+ }
+
+ /**
+ * Constructs a tokenizer splitting on the specified delimiter string.
+ *
+ * @param input the string which is to be parsed
+ * @param delim the field delimiter string
+ */
+ public StrTokenizer(String input, String delim) {
+ this(input);
+ setDelimiterString(delim);
+ }
+
+ /**
+ * Constructs a tokenizer splitting using the specified delimiter matcher.
+ *
+ * @param input the string which is to be parsed
+ * @param delim the field delimiter matcher
+ */
+ public StrTokenizer(String input, StrMatcher delim) {
+ this(input);
+ setDelimiterMatcher(delim);
+ }
+
+ /**
+ * Constructs a tokenizer splitting on the specified delimiter character
+ * and handling quotes using the specified quote character.
+ *
+ * @param input the string which is to be parsed
+ * @param delim the field delimiter character
+ * @param quote the field quoted string character
+ */
+ public StrTokenizer(String input, char delim, char quote) {
+ this(input, delim);
+ setQuoteChar(quote);
+ }
+
+ /**
+ * Constructs a tokenizer splitting using the specified delimiter matcher
+ * and handling quotes using the specified quote matcher.
+ *
+ * @param input the string which is to be parsed
+ * @param delim the field delimiter matcher
+ * @param quote the field quoted string matcher
+ */
+ public StrTokenizer(String input, StrMatcher delim, StrMatcher quote) {
+ this(input, delim);
+ setQuoteMatcher(quote);
+ }
+
+ /**
+ * Constructs a tokenizer splitting on space, tab, newline and formfeed
+ * as per StringTokenizer.
+ *
+ * The input character array is not cloned, and must not be altered after
+ * passing in to this method.
+ *
+ * @param input the string which is to be parsed, not cloned
+ */
+ public StrTokenizer(char[] input) {
+ super();
+ this.chars = input;
+ }
+
+ /**
+ * Constructs a tokenizer splitting on the specified character.
+ *
+ * The input character array is not cloned, and must not be altered after
+ * passing in to this method.
+ *
+ * @param input the string which is to be parsed, not cloned
+ * @param delim the field delimiter character
+ */
+ public StrTokenizer(char[] input, char delim) {
+ this(input);
+ setDelimiterChar(delim);
+ }
+
+ /**
+ * Constructs a tokenizer splitting on the specified string.
+ *
+ * The input character array is not cloned, and must not be altered after
+ * passing in to this method.
+ *
+ * @param input the string which is to be parsed, not cloned
+ * @param delim the field delimiter string
+ */
+ public StrTokenizer(char[] input, String delim) {
+ this(input);
+ setDelimiterString(delim);
+ }
+
+ /**
+ * Constructs a tokenizer splitting using the specified delimiter matcher.
+ *
+ * The input character array is not cloned, and must not be altered after
+ * passing in to this method.
+ *
+ * @param input the string which is to be parsed, not cloned
+ * @param delim the field delimiter matcher
+ */
+ public StrTokenizer(char[] input, StrMatcher delim) {
+ this(input);
+ setDelimiterMatcher(delim);
+ }
+
+ /**
+ * Constructs a tokenizer splitting on the specified delimiter character
+ * and handling quotes using the specified quote character.
+ *
+ * The input character array is not cloned, and must not be altered after
+ * passing in to this method.
+ *
+ * @param input the string which is to be parsed, not cloned
+ * @param delim the field delimiter character
+ * @param quote the field quoted string character
+ */
+ public StrTokenizer(char[] input, char delim, char quote) {
+ this(input, delim);
+ setQuoteChar(quote);
+ }
+
+ /**
+ * Constructs a tokenizer splitting using the specified delimiter matcher
+ * and handling quotes using the specified quote matcher.
+ *
+ * The input character array is not cloned, and must not be altered after
+ * passing in to this method.
+ *
+ * @param input the string which is to be parsed, not cloned
+ * @param delim the field delimiter character
+ * @param quote the field quoted string character
+ */
+ public StrTokenizer(char[] input, StrMatcher delim, StrMatcher quote) {
+ this(input, delim);
+ setQuoteMatcher(quote);
+ }
+
+ // API
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the number of tokens found in the String.
+ *
+ * @return the number of matched tokens
+ */
+ public int size() {
+ checkTokenized();
+ return tokens.length;
+ }
+
+ /**
+ * Gets the next token from the String.
+ * Equivalent to {@link #next()} except it returns null rather than
+ * throwing {@link NoSuchElementException} when no tokens remain.
+ *
+ * @return the next sequential token, or null when no more tokens are found
+ */
+ public String nextToken() {
+ if (hasNext()) {
+ return tokens[tokenPos++];
+ }
+ return null;
+ }
+
+ /**
+ * Gets the previous token from the String.
+ *
+ * @return the previous sequential token, or null when no more tokens are found
+ */
+ public String previousToken() {
+ if (hasPrevious()) {
+ return tokens[--tokenPos];
+ }
+ return null;
+ }
+
+ /**
+ * Gets a copy of the full token list as an independent modifiable array.
+ *
+ * @return the tokens as a String array
+ */
+ public String[] getTokenArray() {
+ checkTokenized();
+ return (String[]) tokens.clone();
+ }
+
+ /**
+ * Gets a copy of the full token list as an independent modifiable list.
+ *
+ * @return the tokens as a String array
+ */
+ public List getTokenList() {
+ checkTokenized();
+ List list = new ArrayList(tokens.length);
+ for (int i = 0; i < tokens.length; i++) {
+ list.add(tokens[i]);
+ }
+ return list;
+ }
+
+ /**
+ * Resets this tokenizer, forgetting all parsing and iteration already completed.
+ *
+ * This method allows the same tokenizer to be reused for the same String.
+ *
+ * @return this, to enable chaining
+ */
+ public StrTokenizer reset() {
+ tokenPos = 0;
+ tokens = null;
+ return this;
+ }
+
+ /**
+ * Reset this tokenizer, giving it a new input string to parse.
+ * In this manner you can re-use a tokenizer with the same settings
+ * on multiple input lines.
+ *
+ * @param input the new string to tokenize, null sets no text to parse
+ * @return this, to enable chaining
+ */
+ public StrTokenizer reset(String input) {
+ reset();
+ if (input != null) {
+ this.chars = input.toCharArray();
+ } else {
+ this.chars = null;
+ }
+ return this;
+ }
+
+ /**
+ * Reset this tokenizer, giving it a new input string to parse.
+ * In this manner you can re-use a tokenizer with the same settings
+ * on multiple input lines.
+ *
+ * The input character array is not cloned, and must not be altered after
+ * passing in to this method.
+ *
+ * @param input the new character array to tokenize, not cloned, null sets no text to parse
+ * @return this, to enable chaining
+ */
+ public StrTokenizer reset(char[] input) {
+ reset();
+ this.chars = input;
+ return this;
+ }
+
+ // ListIterator
+ //-----------------------------------------------------------------------
+ /**
+ * Checks whether there are any more tokens.
+ *
+ * @return true if there are more tokens
+ */
+ public boolean hasNext() {
+ checkTokenized();
+ return tokenPos < tokens.length;
+ }
+
+ /**
+ * Gets the next token.
+ *
+ * @return the next String token
+ * @throws NoSuchElementException if there are no more elements
+ */
+ public Object next() {
+ if (hasNext()) {
+ return tokens[tokenPos++];
+ }
+ throw new NoSuchElementException();
+ }
+
+ /**
+ * Gets the index of the next token to return.
+ *
+ * @return the next token index
+ */
+ public int nextIndex() {
+ return tokenPos;
+ }
+
+ /**
+ * Checks whether there are any previous tokens that can be iterated to.
+ *
+ * @return true if there are previous tokens
+ */
+ public boolean hasPrevious() {
+ checkTokenized();
+ return tokenPos > 0;
+ }
+
+ /**
+ * Gets the token previous to the last returned token.
+ *
+ * @return the previous token
+ */
+ public Object previous() {
+ if (hasPrevious()) {
+ return tokens[--tokenPos];
+ }
+ throw new NoSuchElementException();
+ }
+
+ /**
+ * Gets the index of the previous token.
+ *
+ * @return the previous token index
+ */
+ public int previousIndex() {
+ return tokenPos - 1;
+ }
+
+ /**
+ * Unsupported ListIterator operation.
+ *
+ * @throws UnsupportedOperationException always
+ */
+ public void remove() {
+ throw new UnsupportedOperationException("remove() is unsupported");
+ }
+
+ /**
+ * Unsupported ListIterator operation.
+ * @param obj this parameter ignored.
+ * @throws UnsupportedOperationException always
+ */
+ public void set(Object obj) {
+ throw new UnsupportedOperationException("set() is unsupported");
+ }
+
+ /**
+ * Unsupported ListIterator operation.
+ * @param obj this parameter ignored.
+ * @throws UnsupportedOperationException always
+ */
+ public void add(Object obj) {
+ throw new UnsupportedOperationException("add() is unsupported");
+ }
+
+ // Implementation
+ //-----------------------------------------------------------------------
+ /**
+ * Checks if tokenization has been done, and if not then do it.
+ */
+ private void checkTokenized() {
+ if (tokens == null) {
+ if (chars == null) {
+ // still call tokenize as subclass may do some work
+ List split = tokenize(null, 0, 0);
+ tokens = (String[]) split.toArray(new String[split.size()]);
+ } else {
+ List split = tokenize(chars, 0, chars.length);
+ tokens = (String[]) split.toArray(new String[split.size()]);
+ }
+ }
+ }
+
+ /**
+ * Internal method to performs the tokenization.
+ *
+ * Most users of this class do not need to call this method. This method
+ * will be called automatically by other (public) methods when required.
+ *
+ * This method exists to allow subclasses to add code before or after the
+ * tokenization. For example, a subclass could alter the character array,
+ * offset or count to be parsed, or call the tokenizer multiple times on
+ * multiple strings. It is also be possible to filter the results.
+ *
+ * StrTokenizer
will always pass a zero offset and a count
+ * equal to the length of the array to this method, however a subclass
+ * may pass other values, or even an entirely different array.
+ *
+ * @param chars the character array being tokenized, may be null
+ * @param offset the start position within the character array, must be valid
+ * @param count the number of characters to tokenize, must be valid
+ * @return the modifiable list of String tokens, unmodifiable if null array or zero count
+ */
+ protected List tokenize(char[] chars, int offset, int count) {
+ if (chars == null || count == 0) {
+ return Collections.EMPTY_LIST;
+ }
+ StrBuilder buf = new StrBuilder();
+ List tokens = new ArrayList();
+ int pos = offset;
+
+ // loop around the entire buffer
+ while (pos >= 0 && pos < count) {
+ // find next token
+ pos = readNextToken(chars, pos, count, buf, tokens);
+
+ // handle case where end of string is a delimiter
+ if (pos >= count) {
+ addToken(tokens, "");
+ }
+ }
+ return tokens;
+ }
+
+ /**
+ * Adds a token to a list, paying attention to the parameters we've set.
+ *
+ * @param list the list to add to
+ * @param tok the token to add
+ */
+ private void addToken(List list, String tok) {
+ if (tok == null || tok.length() == 0) {
+ if (isIgnoreEmptyTokens()) {
+ return;
+ }
+ if (isEmptyTokenAsNull()) {
+ tok = null;
+ }
+ }
+ list.add(tok);
+ }
+
+ /**
+ * Reads character by character through the String to get the next token.
+ *
+ * @param chars the character array being tokenized
+ * @param start the first character of field
+ * @param len the length of the character array being tokenized
+ * @param workArea a temporary work area
+ * @param tokens the list of parsed tokens
+ * @return the starting position of the next field (the character
+ * immediately after the delimiter), or -1 if end of string found
+ */
+ private int readNextToken(char[] chars, int start, int len, StrBuilder workArea, List tokens) {
+ // skip all leading whitespace, unless it is the
+ // field delimiter or the quote character
+ while (start < len) {
+ int removeLen = Math.max(
+ getIgnoredMatcher().isMatch(chars, start, start, len),
+ getTrimmerMatcher().isMatch(chars, start, start, len));
+ if (removeLen == 0 ||
+ getDelimiterMatcher().isMatch(chars, start, start, len) > 0 ||
+ getQuoteMatcher().isMatch(chars, start, start, len) > 0) {
+ break;
+ }
+ start += removeLen;
+ }
+
+ // handle reaching end
+ if (start >= len) {
+ addToken(tokens, "");
+ return -1;
+ }
+
+ // handle empty token
+ int delimLen = getDelimiterMatcher().isMatch(chars, start, start, len);
+ if (delimLen > 0) {
+ addToken(tokens, "");
+ return start + delimLen;
+ }
+
+ // handle found token
+ int quoteLen = getQuoteMatcher().isMatch(chars, start, start, len);
+ if (quoteLen > 0) {
+ return readWithQuotes(chars, start + quoteLen, len, workArea, tokens, start, quoteLen);
+ }
+ return readWithQuotes(chars, start, len, workArea, tokens, 0, 0);
+ }
+
+ /**
+ * Reads a possibly quoted string token.
+ *
+ * @param chars the character array being tokenized
+ * @param start the first character of field
+ * @param len the length of the character array being tokenized
+ * @param workArea a temporary work area
+ * @param tokens the list of parsed tokens
+ * @param quoteStart the start position of the matched quote, 0 if no quoting
+ * @param quoteLen the length of the matched quote, 0 if no quoting
+ * @return the starting position of the next field (the character
+ * immediately after the delimiter, or if end of string found,
+ * then the length of string
+ */
+ private int readWithQuotes(char[] chars, int start, int len, StrBuilder workArea,
+ List tokens, int quoteStart, int quoteLen)
+ {
+ // Loop until we've found the end of the quoted
+ // string or the end of the input
+ workArea.clear();
+ int pos = start;
+ boolean quoting = (quoteLen > 0);
+ int trimStart = 0;
+
+ while (pos < len) {
+ // quoting mode can occur several times throughout a string
+ // we must switch between quoting and non-quoting until we
+ // encounter a non-quoted delimiter, or end of string
+ if (quoting) {
+ // In quoting mode
+
+ // If we've found a quote character, see if it's
+ // followed by a second quote. If so, then we need
+ // to actually put the quote character into the token
+ // rather than end the token.
+ if (isQuote(chars, pos, len, quoteStart, quoteLen)) {
+ if (isQuote(chars, pos + quoteLen, len, quoteStart, quoteLen)) {
+ // matched pair of quotes, thus an escaped quote
+ workArea.append(chars, pos, quoteLen);
+ pos += (quoteLen * 2);
+ trimStart = workArea.size();
+ continue;
+ }
+
+ // end of quoting
+ quoting = false;
+ pos += quoteLen;
+ continue;
+ }
+
+ // copy regular character from inside quotes
+ workArea.append(chars[pos++]);
+ trimStart = workArea.size();
+
+ } else {
+ // Not in quoting mode
+
+ // check for delimiter, and thus end of token
+ int delimLen = getDelimiterMatcher().isMatch(chars, pos, start, len);
+ if (delimLen > 0) {
+ // return condition when end of token found
+ addToken(tokens, workArea.substring(0, trimStart));
+ return pos + delimLen;
+ }
+
+ // check for quote, and thus back into quoting mode
+ if (quoteLen > 0) {
+ if (isQuote(chars, pos, len, quoteStart, quoteLen)) {
+ quoting = true;
+ pos += quoteLen;
+ continue;
+ }
+ }
+
+ // check for ignored (outside quotes), and ignore
+ int ignoredLen = getIgnoredMatcher().isMatch(chars, pos, start, len);
+ if (ignoredLen > 0) {
+ pos += ignoredLen;
+ continue;
+ }
+
+ // check for trimmed character
+ // don't yet know if its at the end, so copy to workArea
+ // use trimStart to keep track of trim at the end
+ int trimmedLen = getTrimmerMatcher().isMatch(chars, pos, start, len);
+ if (trimmedLen > 0) {
+ workArea.append(chars, pos, trimmedLen);
+ pos += trimmedLen;
+ continue;
+ }
+
+ // copy regular character from outside quotes
+ workArea.append(chars[pos++]);
+ trimStart = workArea.size();
+ }
+ }
+
+ // return condition when end of string found
+ addToken(tokens, workArea.substring(0, trimStart));
+ return -1;
+ }
+
+ /**
+ * Checks if the characters at the index specified match the quote
+ * already matched in readNextToken().
+ *
+ * @param chars the character array being tokenized
+ * @param pos the position to check for a quote
+ * @param len the length of the character array being tokenized
+ * @param quoteStart the start position of the matched quote, 0 if no quoting
+ * @param quoteLen the length of the matched quote, 0 if no quoting
+ * @return true if a quote is matched
+ */
+ private boolean isQuote(char[] chars, int pos, int len, int quoteStart, int quoteLen) {
+ for (int i = 0; i < quoteLen; i++) {
+ if ((pos + i) >= len || chars[pos + i] != chars[quoteStart + i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // Delimiter
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the field delimiter matcher.
+ *
+ * @return the delimiter matcher in use
+ */
+ public StrMatcher getDelimiterMatcher() {
+ return this.delimMatcher;
+ }
+
+ /**
+ * Sets the field delimiter matcher.
+ *
+ * The delimitier is used to separate one token from another.
+ *
+ * @param delim the delimiter matcher to use
+ * @return this, to enable chaining
+ */
+ public StrTokenizer setDelimiterMatcher(StrMatcher delim) {
+ if (delim == null) {
+ this.delimMatcher = StrMatcher.noneMatcher();
+ } else {
+ this.delimMatcher = delim;
+ }
+ return this;
+ }
+
+ /**
+ * Sets the field delimiter character.
+ *
+ * @param delim the delimiter character to use
+ * @return this, to enable chaining
+ */
+ public StrTokenizer setDelimiterChar(char delim) {
+ return setDelimiterMatcher(StrMatcher.charMatcher(delim));
+ }
+
+ /**
+ * Sets the field delimiter string.
+ *
+ * @param delim the delimiter string to use
+ * @return this, to enable chaining
+ */
+ public StrTokenizer setDelimiterString(String delim) {
+ return setDelimiterMatcher(StrMatcher.stringMatcher(delim));
+ }
+
+ // Quote
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the quote matcher currently in use.
+ *
+ * The quote character is used to wrap data between the tokens.
+ * This enables delimiters to be entered as data.
+ * The default value is '"' (double quote).
+ *
+ * @return the quote matcher in use
+ */
+ public StrMatcher getQuoteMatcher() {
+ return quoteMatcher;
+ }
+
+ /**
+ * Set the quote matcher to use.
+ *
+ * The quote character is used to wrap data between the tokens.
+ * This enables delimiters to be entered as data.
+ *
+ * @param quote the quote matcher to use, null ignored
+ * @return this, to enable chaining
+ */
+ public StrTokenizer setQuoteMatcher(StrMatcher quote) {
+ if (quote != null) {
+ this.quoteMatcher = quote;
+ }
+ return this;
+ }
+
+ /**
+ * Sets the quote character to use.
+ *
+ * The quote character is used to wrap data between the tokens.
+ * This enables delimiters to be entered as data.
+ *
+ * @param quote the quote character to use
+ * @return this, to enable chaining
+ */
+ public StrTokenizer setQuoteChar(char quote) {
+ return setQuoteMatcher(StrMatcher.charMatcher(quote));
+ }
+
+ // Ignored
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the ignored character matcher.
+ *
+ * These characters are ignored when parsing the String, unless they are
+ * within a quoted region.
+ * The default value is not to ignore anything.
+ *
+ * @return the ignored matcher in use
+ */
+ public StrMatcher getIgnoredMatcher() {
+ return ignoredMatcher;
+ }
+
+ /**
+ * Set the matcher for characters to ignore.
+ *
+ * These characters are ignored when parsing the String, unless they are
+ * within a quoted region.
+ *
+ * @param ignored the ignored matcher to use, null ignored
+ * @return this, to enable chaining
+ */
+ public StrTokenizer setIgnoredMatcher(StrMatcher ignored) {
+ if (ignored != null) {
+ this.ignoredMatcher = ignored;
+ }
+ return this;
+ }
+
+ /**
+ * Set the character to ignore.
+ *
+ * This character is ignored when parsing the String, unless it is
+ * within a quoted region.
+ *
+ * @param ignored the ignored character to use
+ * @return this, to enable chaining
+ */
+ public StrTokenizer setIgnoredChar(char ignored) {
+ return setIgnoredMatcher(StrMatcher.charMatcher(ignored));
+ }
+
+ // Trimmer
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the trimmer character matcher.
+ *
+ * These characters are trimmed off on each side of the delimiter
+ * until the token or quote is found.
+ * The default value is not to trim anything.
+ *
+ * @return the trimmer matcher in use
+ */
+ public StrMatcher getTrimmerMatcher() {
+ return trimmerMatcher;
+ }
+
+ /**
+ * Sets the matcher for characters to trim.
+ *
+ * These characters are trimmed off on each side of the delimiter
+ * until the token or quote is found.
+ *
+ * @param trimmer the trimmer matcher to use, null ignored
+ * @return this, to enable chaining
+ */
+ public StrTokenizer setTrimmerMatcher(StrMatcher trimmer) {
+ if (trimmer != null) {
+ this.trimmerMatcher = trimmer;
+ }
+ return this;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets whether the tokenizer currently returns empty tokens as null.
+ * The default for this property is false.
+ *
+ * @return true if empty tokens are returned as null
+ */
+ public boolean isEmptyTokenAsNull() {
+ return this.emptyAsNull;
+ }
+
+ /**
+ * Sets whether the tokenizer should return empty tokens as null.
+ * The default for this property is false.
+ *
+ * @param emptyAsNull whether empty tokens are returned as null
+ * @return this, to enable chaining
+ */
+ public StrTokenizer setEmptyTokenAsNull(boolean emptyAsNull) {
+ this.emptyAsNull = emptyAsNull;
+ return this;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets whether the tokenizer currently ignores empty tokens.
+ * The default for this property is true.
+ *
+ * @return true if empty tokens are not returned
+ */
+ public boolean isIgnoreEmptyTokens() {
+ return ignoreEmptyTokens;
+ }
+
+ /**
+ * Sets whether the tokenizer should ignore and not return empty tokens.
+ * The default for this property is true.
+ *
+ * @param ignoreEmptyTokens whether empty tokens are not returned
+ * @return this, to enable chaining
+ */
+ public StrTokenizer setIgnoreEmptyTokens(boolean ignoreEmptyTokens) {
+ this.ignoreEmptyTokens = ignoreEmptyTokens;
+ return this;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the String content that the tokenizer is parsing.
+ *
+ * @return the string content being parsed
+ */
+ public String getContent() {
+ if (chars == null) {
+ return null;
+ }
+ return new String(chars);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Creates a new instance of this Tokenizer. The new instance is reset so
+ * that it will be at the start of the token list.
+ * If a {@link CloneNotSupportedException} is caught, return null
.
+ *
+ * @return a new instance of this Tokenizer which has been reset.
+ */
+ public Object clone() {
+ try {
+ return cloneReset();
+ } catch (CloneNotSupportedException ex) {
+ return null;
+ }
+ }
+
+ /**
+ * Creates a new instance of this Tokenizer. The new instance is reset so that
+ * it will be at the start of the token list.
+ *
+ * @return a new instance of this Tokenizer which has been reset.
+ * @throws CloneNotSupportedException if there is a problem cloning
+ */
+ Object cloneReset() throws CloneNotSupportedException {
+ // this method exists to enable 100% test coverage
+ StrTokenizer cloned = (StrTokenizer) super.clone();
+ if (cloned.chars != null) {
+ cloned.chars = (char[]) cloned.chars.clone();
+ }
+ cloned.reset();
+ return cloned;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the String content that the tokenizer is parsing.
+ *
+ * @return the string content being parsed
+ */
+ public String toString() {
+ if (tokens == null) {
+ return "StrTokenizer[not tokenized yet]";
+ }
+ return "StrTokenizer" + getTokenList();
+ }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/text/package.html
===================================================================
diff -u
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/text/package.html (revision 0)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/text/package.html (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -0,0 +1,26 @@
+
+
+
+
+Provides classes for handling and manipulating text, partly as an extension to {@link java.text}.
+The classes in this package are, for the most part, intended to be instantiated.
+(ie. they are not utility classes with lots of static methods)
+
+@since 2.1
+
+
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/time/DateFormatUtils.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/time/DateFormatUtils.java (.../DateFormatUtils.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/time/DateFormatUtils.java (.../DateFormatUtils.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,80 +1,44 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang.time;
+import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
/**
- * Date and time formatting utilites and constants.
+ * Date and time formatting utilities and constants.
*
* Formatting is performed using the
* {@link org.apache.commons.lang.time.FastDateFormat} class.
*
+ * @author Apache Software Foundation
* @author Apache Ant - DateUtils
* @author Stephane Bailliez
* @author Stefan Bodewig
- * @author Stephen Colebourne
* @author Gary Gregory
* @since 2.0
* @version $Id$
*/
public class DateFormatUtils {
/**
- * ISO8601 formatter for date-time witout time zone.
+ * ISO8601 formatter for date-time without time zone.
* The format used is yyyy-MM-dd'T'HH:mm:ss.
*/
public static final FastDateFormat ISO_DATETIME_FORMAT
@@ -150,10 +114,11 @@
* to operate.
*/
public DateFormatUtils() {
+ super();
}
/**
- * Format a date/time into a specific pattern using the UTC time zone.
+ * Formats a date/time into a specific pattern using the UTC time zone.
*
* @param millis the date to format expressed in milliseconds
* @param pattern the pattern to use to format the date
@@ -164,7 +129,7 @@
}
/**
- * Format a date/time into a specific pattern using the UTC time zone.
+ * Formats a date/time into a specific pattern using the UTC time zone.
*
* @param date the date to format
* @param pattern the pattern to use to format the date
@@ -175,7 +140,7 @@
}
/**
- * Format a date/time into a specific pattern using the UTC time zone.
+ * Formats a date/time into a specific pattern using the UTC time zone.
*
* @param millis the date to format expressed in milliseconds
* @param pattern the pattern to use to format the date
@@ -187,7 +152,7 @@
}
/**
- * Format a date/time into a specific pattern using the UTC time zone.
+ * Formats a date/time into a specific pattern using the UTC time zone.
*
* @param date the date to format
* @param pattern the pattern to use to format the date
@@ -199,7 +164,7 @@
}
/**
- * Format a date/time into a specific pattern.
+ * Formats a date/time into a specific pattern.
*
* @param millis the date to format expressed in milliseconds
* @param pattern the pattern to use to format the date
@@ -210,7 +175,7 @@
}
/**
- * Format a date/time into a specific pattern.
+ * Formats a date/time into a specific pattern.
*
* @param date the date to format
* @param pattern the pattern to use to format the date
@@ -219,9 +184,22 @@
public static String format(Date date, String pattern) {
return format(date, pattern, null, null);
}
+
+ /**
+ * Formats a calendar into a specific pattern.
+ *
+ * @param calendar the calendar to format
+ * @param pattern the pattern to use to format the calendar
+ * @return the formatted calendar
+ * @see FastDateFormat#format(Calendar)
+ * @since 2.4
+ */
+ public static String format(Calendar calendar, String pattern) {
+ return format(calendar, pattern, null, null);
+ }
/**
- * Format a date/time into a specific pattern in a time zone.
+ * Formats a date/time into a specific pattern in a time zone.
*
* @param millis the time expressed in milliseconds
* @param pattern the pattern to use to format the date
@@ -233,7 +211,7 @@
}
/**
- * Format a date/time into a specific pattern in a time zone.
+ * Formats a date/time into a specific pattern in a time zone.
*
* @param date the date to format
* @param pattern the pattern to use to format the date
@@ -245,8 +223,22 @@
}
/**
- * Format a date/time into a specific pattern in a locale.
+ * Formats a calendar into a specific pattern in a time zone.
*
+ * @param calendar the calendar to format
+ * @param pattern the pattern to use to format the calendar
+ * @param timeZone the time zone to use, may be null
+ * @return the formatted calendar
+ * @see FastDateFormat#format(Calendar)
+ * @since 2.4
+ */
+ public static String format(Calendar calendar, String pattern, TimeZone timeZone) {
+ return format(calendar, pattern, timeZone, null);
+ }
+
+ /**
+ * Formats a date/time into a specific pattern in a locale.
+ *
* @param millis the date to format expressed in milliseconds
* @param pattern the pattern to use to format the date
* @param locale the locale to use, may be null
@@ -257,7 +249,7 @@
}
/**
- * Format a date/time into a specific pattern in a locale.
+ * Formats a date/time into a specific pattern in a locale.
*
* @param date the date to format
* @param pattern the pattern to use to format the date
@@ -269,8 +261,22 @@
}
/**
- * Format a date/time into a specific pattern in a time zone and locale.
+ * Formats a calendar into a specific pattern in a locale.
*
+ * @param calendar the calendar to format
+ * @param pattern the pattern to use to format the calendar
+ * @param locale the locale to use, may be null
+ * @return the formatted calendar
+ * @see FastDateFormat#format(Calendar)
+ * @since 2.4
+ */
+ public static String format(Calendar calendar, String pattern, Locale locale) {
+ return format(calendar, pattern, null, locale);
+ }
+
+ /**
+ * Formats a date/time into a specific pattern in a time zone and locale.
+ *
* @param millis the date to format expressed in milliseconds
* @param pattern the pattern to use to format the date
* @param timeZone the time zone to use, may be null
@@ -282,7 +288,7 @@
}
/**
- * Format a date/time into a specific pattern in a time zone and locale.
+ * Formats a date/time into a specific pattern in a time zone and locale.
*
* @param date the date to format
* @param pattern the pattern to use to format the date
@@ -295,4 +301,20 @@
return df.format(date);
}
+ /**
+ * Formats a calendar into a specific pattern in a time zone and locale.
+ *
+ * @param calendar the calendar to format
+ * @param pattern the pattern to use to format the calendar
+ * @param timeZone the time zone to use, may be null
+ * @param locale the locale to use, may be null
+ * @return the formatted calendar
+ * @see FastDateFormat#format(Calendar)
+ * @since 2.4
+ */
+ public static String format(Calendar calendar, String pattern, TimeZone timeZone, Locale locale) {
+ FastDateFormat df = FastDateFormat.getInstance(pattern, timeZone, locale);
+ return df.format(calendar);
+ }
+
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/time/DateUtils.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/time/DateUtils.java (.../DateUtils.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/time/DateUtils.java (.../DateUtils.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,73 +1,55 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang.time;
+import java.text.ParseException;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
-import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.TimeZone;
+import org.apache.commons.lang.StringUtils;
+
/**
* A suite of utilities surrounding the use of the
* {@link java.util.Calendar} and {@link java.util.Date} object.
+ *
+ * DateUtils contains a lot of common methods considering manipulations
+ * of Dates or Calendars. Some methods require some extra explanation.
+ * The truncate, ceiling and round methods could be considered the Math.floor(),
+ * Math.ceil() or Math.round versions for dates
+ * This way date-fields will be ignored in bottom-up order.
+ * As a complement to these methods we've introduced some fragment-methods.
+ * With these methods the Date-fields will be ignored in top-down order.
+ * Since a date without a year is not a valid date, you have to decide in what
+ * kind of date-field you want your result, for instance milliseconds or days.
+ *
+ *
+ *
*
+ * @author Apache Software Foundation
* @author Serge Knystautas
- * @author Stephen Colebourne
* @author Janek Bogucki
* @author Gary Gregory
+ * @author Phil Steitz
+ * @author Robert Scholte
* @since 2.0
* @version $Id$
*/
@@ -79,20 +61,24 @@
public static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone("GMT");
/**
* Number of milliseconds in a standard second.
+ * @since 2.1
*/
- public static final int MILLIS_IN_SECOND = 1000;
+ public static final long MILLIS_PER_SECOND = 1000;
/**
* Number of milliseconds in a standard minute.
+ * @since 2.1
*/
- public static final int MILLIS_IN_MINUTE = 60 * 1000;
+ public static final long MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND;
/**
* Number of milliseconds in a standard hour.
+ * @since 2.1
*/
- public static final int MILLIS_IN_HOUR = 60 * 60 * 1000;
+ public static final long MILLIS_PER_HOUR = 60 * MILLIS_PER_MINUTE;
/**
* Number of milliseconds in a standard day.
+ * @since 2.1
*/
- public static final int MILLIS_IN_DAY = 24 * 60 * 60 * 1000;
+ public static final long MILLIS_PER_DAY = 24 * MILLIS_PER_HOUR;
/**
* This is half a month, so this represents whether a date is in the top
@@ -105,7 +91,9 @@
{Calendar.SECOND},
{Calendar.MINUTE},
{Calendar.HOUR_OF_DAY, Calendar.HOUR},
- {Calendar.DATE, Calendar.DAY_OF_MONTH, Calendar.AM_PM /* Calendar.DAY_OF_YEAR, Calendar.DAY_OF_WEEK, Calendar.DAY_OF_WEEK_IN_MONTH */},
+ {Calendar.DATE, Calendar.DAY_OF_MONTH, Calendar.AM_PM
+ /* Calendar.DAY_OF_YEAR, Calendar.DAY_OF_WEEK, Calendar.DAY_OF_WEEK_IN_MONTH */
+ },
{Calendar.MONTH, DateUtils.SEMI_MONTH},
{Calendar.YEAR},
{Calendar.ERA}};
@@ -141,6 +129,21 @@
public final static int RANGE_MONTH_MONDAY = 6;
/**
+ * Constant marker for truncating
+ */
+ private final static int MODIFY_TRUNCATE = 0;
+
+ /**
+ * Constant marker for rounding
+ */
+ private final static int MODIFY_ROUND = 1;
+
+ /**
+ * Constant marker for ceiling
+ */
+ private final static int MODIFY_CEILING= 2;
+
+ /**
* DateUtils
instances should NOT be constructed in
* standard programming. Instead, the class should be used as
* DateUtils.parse(str);
.
@@ -149,10 +152,531 @@
* instance to operate.
*/
public DateUtils() {
+ super();
}
//-----------------------------------------------------------------------
/**
+ * Checks if two date objects are on the same day ignoring time.
+ *
+ * 28 Mar 2002 13:45 and 28 Mar 2002 06:01 would return true.
+ * 28 Mar 2002 13:45 and 12 Mar 2002 13:45 would return false.
+ *
+ *
+ * @param date1 the first date, not altered, not null
+ * @param date2 the second date, not altered, not null
+ * @return true if they represent the same day
+ * @throws IllegalArgumentException if either date is null
+ * @since 2.1
+ */
+ public static boolean isSameDay(Date date1, Date date2) {
+ if (date1 == null || date2 == null) {
+ throw new IllegalArgumentException("The date must not be null");
+ }
+ Calendar cal1 = Calendar.getInstance();
+ cal1.setTime(date1);
+ Calendar cal2 = Calendar.getInstance();
+ cal2.setTime(date2);
+ return isSameDay(cal1, cal2);
+ }
+
+ /**
+ * Checks if two calendar objects are on the same day ignoring time.
+ *
+ * 28 Mar 2002 13:45 and 28 Mar 2002 06:01 would return true.
+ * 28 Mar 2002 13:45 and 12 Mar 2002 13:45 would return false.
+ *
+ *
+ * @param cal1 the first calendar, not altered, not null
+ * @param cal2 the second calendar, not altered, not null
+ * @return true if they represent the same day
+ * @throws IllegalArgumentException if either calendar is null
+ * @since 2.1
+ */
+ public static boolean isSameDay(Calendar cal1, Calendar cal2) {
+ if (cal1 == null || cal2 == null) {
+ throw new IllegalArgumentException("The date must not be null");
+ }
+ return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) &&
+ cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
+ cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR));
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Checks if two date objects represent the same instant in time.
+ *
+ * This method compares the long millisecond time of the two objects.
+ *
+ * @param date1 the first date, not altered, not null
+ * @param date2 the second date, not altered, not null
+ * @return true if they represent the same millisecond instant
+ * @throws IllegalArgumentException if either date is null
+ * @since 2.1
+ */
+ public static boolean isSameInstant(Date date1, Date date2) {
+ if (date1 == null || date2 == null) {
+ throw new IllegalArgumentException("The date must not be null");
+ }
+ return date1.getTime() == date2.getTime();
+ }
+
+ /**
+ * Checks if two calendar objects represent the same instant in time.
+ *
+ * This method compares the long millisecond time of the two objects.
+ *
+ * @param cal1 the first calendar, not altered, not null
+ * @param cal2 the second calendar, not altered, not null
+ * @return true if they represent the same millisecond instant
+ * @throws IllegalArgumentException if either date is null
+ * @since 2.1
+ */
+ public static boolean isSameInstant(Calendar cal1, Calendar cal2) {
+ if (cal1 == null || cal2 == null) {
+ throw new IllegalArgumentException("The date must not be null");
+ }
+ return cal1.getTime().getTime() == cal2.getTime().getTime();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Checks if two calendar objects represent the same local time.
+ *
+ * This method compares the values of the fields of the two objects.
+ * In addition, both calendars must be the same of the same type.
+ *
+ * @param cal1 the first calendar, not altered, not null
+ * @param cal2 the second calendar, not altered, not null
+ * @return true if they represent the same millisecond instant
+ * @throws IllegalArgumentException if either date is null
+ * @since 2.1
+ */
+ public static boolean isSameLocalTime(Calendar cal1, Calendar cal2) {
+ if (cal1 == null || cal2 == null) {
+ throw new IllegalArgumentException("The date must not be null");
+ }
+ return (cal1.get(Calendar.MILLISECOND) == cal2.get(Calendar.MILLISECOND) &&
+ cal1.get(Calendar.SECOND) == cal2.get(Calendar.SECOND) &&
+ cal1.get(Calendar.MINUTE) == cal2.get(Calendar.MINUTE) &&
+ cal1.get(Calendar.HOUR) == cal2.get(Calendar.HOUR) &&
+ cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR) &&
+ cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
+ cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) &&
+ cal1.getClass() == cal2.getClass());
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Parses a string representing a date by trying a variety of different parsers.
+ *
+ * The parse will try each parse pattern in turn.
+ * A parse is only deemed successful if it parses the whole of the input string.
+ * If no parse patterns match, a ParseException is thrown.
+ * The parser will be lenient toward the parsed date.
+ *
+ * @param str the date to parse, not null
+ * @param parsePatterns the date format patterns to use, see SimpleDateFormat, not null
+ * @return the parsed date
+ * @throws IllegalArgumentException if the date string or pattern array is null
+ * @throws ParseException if none of the date patterns were suitable (or there were none)
+ */
+ public static Date parseDate(String str, String[] parsePatterns) throws ParseException {
+ return parseDateWithLeniency(str, parsePatterns, true);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Parses a string representing a date by trying a variety of different parsers.
+ *
+ * The parse will try each parse pattern in turn.
+ * A parse is only deemed successful if it parses the whole of the input string.
+ * If no parse patterns match, a ParseException is thrown.
+ * The parser parses strictly - it does not allow for dates such as "February 942, 1996".
+ *
+ * @param str the date to parse, not null
+ * @param parsePatterns the date format patterns to use, see SimpleDateFormat, not null
+ * @return the parsed date
+ * @throws IllegalArgumentException if the date string or pattern array is null
+ * @throws ParseException if none of the date patterns were suitable
+ * @since 2.5
+ */
+ public static Date parseDateStrictly(String str, String[] parsePatterns) throws ParseException {
+ return parseDateWithLeniency(str, parsePatterns, false);
+ }
+
+ /**
+ * Parses a string representing a date by trying a variety of different parsers.
+ *
+ * The parse will try each parse pattern in turn.
+ * A parse is only deemed successful if it parses the whole of the input string.
+ * If no parse patterns match, a ParseException is thrown.
+ *
+ * @param str the date to parse, not null
+ * @param parsePatterns the date format patterns to use, see SimpleDateFormat, not null
+ * @param lenient Specify whether or not date/time parsing is to be lenient.
+ * @return the parsed date
+ * @throws IllegalArgumentException if the date string or pattern array is null
+ * @throws ParseException if none of the date patterns were suitable
+ * @see java.util.Calender#isLenient()
+ */
+ private static Date parseDateWithLeniency(String str, String[] parsePatterns,
+ boolean lenient) throws ParseException {
+ if (str == null || parsePatterns == null) {
+ throw new IllegalArgumentException("Date and Patterns must not be null");
+ }
+
+ SimpleDateFormat parser = new SimpleDateFormat();
+ parser.setLenient(lenient);
+ ParsePosition pos = new ParsePosition(0);
+ for (int i = 0; i < parsePatterns.length; i++) {
+
+ String pattern = parsePatterns[i];
+
+ // LANG-530 - need to make sure 'ZZ' output doesn't get passed to SimpleDateFormat
+ if (parsePatterns[i].endsWith("ZZ")) {
+ pattern = pattern.substring(0, pattern.length() - 1);
+ }
+
+ parser.applyPattern(pattern);
+ pos.setIndex(0);
+
+ String str2 = str;
+ // LANG-530 - need to make sure 'ZZ' output doesn't hit SimpleDateFormat as it will ParseException
+ if (parsePatterns[i].endsWith("ZZ")) {
+ int signIdx = indexOfSignChars(str2, 0);
+ while (signIdx >=0) {
+ str2 = reformatTimezone(str2, signIdx);
+ signIdx = indexOfSignChars(str2, ++signIdx);
+ }
+ }
+
+ Date date = parser.parse(str2, pos);
+ if (date != null && pos.getIndex() == str2.length()) {
+ return date;
+ }
+ }
+ throw new ParseException("Unable to parse the date: " + str, -1);
+ }
+
+ /**
+ * Index of sign charaters (i.e. '+' or '-').
+ *
+ * @param str The string to search
+ * @param startPos The start position
+ * @return the index of the first sign character or -1 if not found
+ */
+ private static int indexOfSignChars(String str, int startPos) {
+ int idx = StringUtils.indexOf(str, '+', startPos);
+ if (idx < 0) {
+ idx = StringUtils.indexOf(str, '-', startPos);
+ }
+ return idx;
+ }
+
+ /**
+ * Reformat the timezone in a date string.
+ *
+ * @param str The input string
+ * @param signIdx The index position of the sign characters
+ * @return The reformatted string
+ */
+ private static String reformatTimezone(String str, int signIdx) {
+ String str2 = str;
+ if (signIdx >= 0 &&
+ signIdx + 5 < str.length() &&
+ Character.isDigit(str.charAt(signIdx + 1)) &&
+ Character.isDigit(str.charAt(signIdx + 2)) &&
+ str.charAt(signIdx + 3) == ':' &&
+ Character.isDigit(str.charAt(signIdx + 4)) &&
+ Character.isDigit(str.charAt(signIdx + 5))) {
+ str2 = str.substring(0, signIdx + 3) + str.substring(signIdx + 4);
+ }
+ return str2;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Adds a number of years to a date returning a new object.
+ * The original date object is unchanged.
+ *
+ * @param date the date, not null
+ * @param amount the amount to add, may be negative
+ * @return the new date object with the amount added
+ * @throws IllegalArgumentException if the date is null
+ */
+ public static Date addYears(Date date, int amount) {
+ return add(date, Calendar.YEAR, amount);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Adds a number of months to a date returning a new object.
+ * The original date object is unchanged.
+ *
+ * @param date the date, not null
+ * @param amount the amount to add, may be negative
+ * @return the new date object with the amount added
+ * @throws IllegalArgumentException if the date is null
+ */
+ public static Date addMonths(Date date, int amount) {
+ return add(date, Calendar.MONTH, amount);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Adds a number of weeks to a date returning a new object.
+ * The original date object is unchanged.
+ *
+ * @param date the date, not null
+ * @param amount the amount to add, may be negative
+ * @return the new date object with the amount added
+ * @throws IllegalArgumentException if the date is null
+ */
+ public static Date addWeeks(Date date, int amount) {
+ return add(date, Calendar.WEEK_OF_YEAR, amount);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Adds a number of days to a date returning a new object.
+ * The original date object is unchanged.
+ *
+ * @param date the date, not null
+ * @param amount the amount to add, may be negative
+ * @return the new date object with the amount added
+ * @throws IllegalArgumentException if the date is null
+ */
+ public static Date addDays(Date date, int amount) {
+ return add(date, Calendar.DAY_OF_MONTH, amount);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Adds a number of hours to a date returning a new object.
+ * The original date object is unchanged.
+ *
+ * @param date the date, not null
+ * @param amount the amount to add, may be negative
+ * @return the new date object with the amount added
+ * @throws IllegalArgumentException if the date is null
+ */
+ public static Date addHours(Date date, int amount) {
+ return add(date, Calendar.HOUR_OF_DAY, amount);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Adds a number of minutes to a date returning a new object.
+ * The original date object is unchanged.
+ *
+ * @param date the date, not null
+ * @param amount the amount to add, may be negative
+ * @return the new date object with the amount added
+ * @throws IllegalArgumentException if the date is null
+ */
+ public static Date addMinutes(Date date, int amount) {
+ return add(date, Calendar.MINUTE, amount);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Adds a number of seconds to a date returning a new object.
+ * The original date object is unchanged.
+ *
+ * @param date the date, not null
+ * @param amount the amount to add, may be negative
+ * @return the new date object with the amount added
+ * @throws IllegalArgumentException if the date is null
+ */
+ public static Date addSeconds(Date date, int amount) {
+ return add(date, Calendar.SECOND, amount);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Adds a number of milliseconds to a date returning a new object.
+ * The original date object is unchanged.
+ *
+ * @param date the date, not null
+ * @param amount the amount to add, may be negative
+ * @return the new date object with the amount added
+ * @throws IllegalArgumentException if the date is null
+ */
+ public static Date addMilliseconds(Date date, int amount) {
+ return add(date, Calendar.MILLISECOND, amount);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Adds to a date returning a new object.
+ * The original date object is unchanged.
+ *
+ * @param date the date, not null
+ * @param calendarField the calendar field to add to
+ * @param amount the amount to add, may be negative
+ * @return the new date object with the amount added
+ * @throws IllegalArgumentException if the date is null
+ * @deprecated Will become privately scoped in 3.0
+ */
+ public static Date add(Date date, int calendarField, int amount) {
+ if (date == null) {
+ throw new IllegalArgumentException("The date must not be null");
+ }
+ Calendar c = Calendar.getInstance();
+ c.setTime(date);
+ c.add(calendarField, amount);
+ return c.getTime();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Sets the years field to a date returning a new object.
+ * The original date object is unchanged.
+ *
+ * @param date the date, not null
+ * @param amount the amount to set
+ * @return a new Date object set with the specified value
+ * @throws IllegalArgumentException if the date is null
+ * @since 2.4
+ */
+ public static Date setYears(Date date, int amount) {
+ return set(date, Calendar.YEAR, amount);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Sets the months field to a date returning a new object.
+ * The original date object is unchanged.
+ *
+ * @param date the date, not null
+ * @param amount the amount to set
+ * @return a new Date object set with the specified value
+ * @throws IllegalArgumentException if the date is null
+ * @since 2.4
+ */
+ public static Date setMonths(Date date, int amount) {
+ return set(date, Calendar.MONTH, amount);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Sets the day of month field to a date returning a new object.
+ * The original date object is unchanged.
+ *
+ * @param date the date, not null
+ * @param amount the amount to set
+ * @return a new Date object set with the specified value
+ * @throws IllegalArgumentException if the date is null
+ * @since 2.4
+ */
+ public static Date setDays(Date date, int amount) {
+ return set(date, Calendar.DAY_OF_MONTH, amount);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Sets the hours field to a date returning a new object. Hours range
+ * from 0-23.
+ * The original date object is unchanged.
+ *
+ * @param date the date, not null
+ * @param amount the amount to set
+ * @return a new Date object set with the specified value
+ * @throws IllegalArgumentException if the date is null
+ * @since 2.4
+ */
+ public static Date setHours(Date date, int amount) {
+ return set(date, Calendar.HOUR_OF_DAY, amount);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Sets the minute field to a date returning a new object.
+ * The original date object is unchanged.
+ *
+ * @param date the date, not null
+ * @param amount the amount to set
+ * @return a new Date object set with the specified value
+ * @throws IllegalArgumentException if the date is null
+ * @since 2.4
+ */
+ public static Date setMinutes(Date date, int amount) {
+ return set(date, Calendar.MINUTE, amount);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Sets the seconds field to a date returning a new object.
+ * The original date object is unchanged.
+ *
+ * @param date the date, not null
+ * @param amount the amount to set
+ * @return a new Date object set with the specified value
+ * @throws IllegalArgumentException if the date is null
+ * @since 2.4
+ */
+ public static Date setSeconds(Date date, int amount) {
+ return set(date, Calendar.SECOND, amount);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Sets the miliseconds field to a date returning a new object.
+ * The original date object is unchanged.
+ *
+ * @param date the date, not null
+ * @param amount the amount to set
+ * @return a new Date object set with the specified value
+ * @throws IllegalArgumentException if the date is null
+ * @since 2.4
+ */
+ public static Date setMilliseconds(Date date, int amount) {
+ return set(date, Calendar.MILLISECOND, amount);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Sets the specified field to a date returning a new object.
+ * This does not use a lenient calendar.
+ * The original date object is unchanged.
+ *
+ * @param date the date, not null
+ * @param calendarField the calendar field to set the amount to
+ * @param amount the amount to set
+ * @return a new Date object set with the specified value
+ * @throws IllegalArgumentException if the date is null
+ * @since 2.4
+ */
+ private static Date set(Date date, int calendarField, int amount) {
+ if (date == null) {
+ throw new IllegalArgumentException("The date must not be null");
+ }
+ // getInstance() returns a new object, so this method is thread safe.
+ Calendar c = Calendar.getInstance();
+ c.setLenient(false);
+ c.setTime(date);
+ c.set(calendarField, amount);
+ return c.getTime();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Convert a Date into a Calendar object.
+ *
+ * @param date the date to convert to a Calendar
+ * @return the created Calendar
+ * @throws NullPointerException if null is passed in
+ * @since 2.6
+ */
+ public static Calendar toCalendar(Date date) {
+ Calendar c = Calendar.getInstance();
+ c.setTime(date);
+ return c;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
* Round this date, leaving the field specified as the most
* significant field.
*
@@ -161,19 +685,32 @@
* 28 Mar 2002 14:00:00.000. If this was passed with MONTH, it
* would return 1 April 2002 0:00:00.000.
*
+ * For a date in a timezone that handles the change to daylight
+ * saving time, rounding to Calendar.HOUR_OF_DAY will behave as follows.
+ * Suppose daylight saving time begins at 02:00 on March 30. Rounding a
+ * date that crosses this time would produce the following values:
+ *
+ * - March 30, 2003 01:10 rounds to March 30, 2003 01:00
+ * - March 30, 2003 01:40 rounds to March 30, 2003 03:00
+ * - March 30, 2003 02:10 rounds to March 30, 2003 03:00
+ * - March 30, 2003 02:40 rounds to March 30, 2003 04:00
+ *
+ *
+ *
* @param date the date to work with
* @param field the field from Calendar
* or SEMI_MONTH
* @return the rounded date
* @throws IllegalArgumentException if the date is null
+ * @throws ArithmeticException if the year is over 280 million
*/
public static Date round(Date date, int field) {
if (date == null) {
throw new IllegalArgumentException("The date must not be null");
}
- GregorianCalendar gval = new GregorianCalendar();
+ Calendar gval = Calendar.getInstance();
gval.setTime(date);
- modify(gval, field, true);
+ modify(gval, field, MODIFY_ROUND);
return gval.getTime();
}
@@ -186,18 +723,31 @@
* 28 Mar 2002 14:00:00.000. If this was passed with MONTH, it
* would return 1 April 2002 0:00:00.000.
*
+ * For a date in a timezone that handles the change to daylight
+ * saving time, rounding to Calendar.HOUR_OF_DAY will behave as follows.
+ * Suppose daylight saving time begins at 02:00 on March 30. Rounding a
+ * date that crosses this time would produce the following values:
+ *
+ * - March 30, 2003 01:10 rounds to March 30, 2003 01:00
+ * - March 30, 2003 01:40 rounds to March 30, 2003 03:00
+ * - March 30, 2003 02:10 rounds to March 30, 2003 03:00
+ * - March 30, 2003 02:40 rounds to March 30, 2003 04:00
+ *
+ *
+ *
* @param date the date to work with
* @param field the field from Calendar
* or SEMI_MONTH
* @return the rounded date (a different object)
* @throws IllegalArgumentException if the date is null
+ * @throws ArithmeticException if the year is over 280 million
*/
public static Calendar round(Calendar date, int field) {
if (date == null) {
throw new IllegalArgumentException("The date must not be null");
}
Calendar rounded = (Calendar) date.clone();
- modify(rounded, field, true);
+ modify(rounded, field, MODIFY_ROUND);
return rounded;
}
@@ -210,13 +760,26 @@
* 28 Mar 2002 14:00:00.000. If this was passed with MONTH, it
* would return 1 April 2002 0:00:00.000.
*
+ * For a date in a timezone that handles the change to daylight
+ * saving time, rounding to Calendar.HOUR_OF_DAY will behave as follows.
+ * Suppose daylight saving time begins at 02:00 on March 30. Rounding a
+ * date that crosses this time would produce the following values:
+ *
+ * - March 30, 2003 01:10 rounds to March 30, 2003 01:00
+ * - March 30, 2003 01:40 rounds to March 30, 2003 03:00
+ * - March 30, 2003 02:10 rounds to March 30, 2003 03:00
+ * - March 30, 2003 02:40 rounds to March 30, 2003 04:00
+ *
+ *
+ *
* @param date the date to work with, either Date or Calendar
* @param field the field from Calendar
* or SEMI_MONTH
* @return the rounded date
* @throws IllegalArgumentException if the date is null
* @throws ClassCastException if the object type is not a Date
* or Calendar
+ * @throws ArithmeticException if the year is over 280 million
*/
public static Date round(Object date, int field) {
if (date == null) {
@@ -246,14 +809,15 @@
* or SEMI_MONTH
* @return the rounded date
* @throws IllegalArgumentException if the date is null
+ * @throws ArithmeticException if the year is over 280 million
*/
public static Date truncate(Date date, int field) {
if (date == null) {
throw new IllegalArgumentException("The date must not be null");
}
- GregorianCalendar gval = new GregorianCalendar();
+ Calendar gval = Calendar.getInstance();
gval.setTime(date);
- modify(gval, field, false);
+ modify(gval, field, MODIFY_TRUNCATE);
return gval.getTime();
}
@@ -271,13 +835,14 @@
* or SEMI_MONTH
* @return the rounded date (a different object)
* @throws IllegalArgumentException if the date is null
+ * @throws ArithmeticException if the year is over 280 million
*/
public static Calendar truncate(Calendar date, int field) {
if (date == null) {
throw new IllegalArgumentException("The date must not be null");
}
Calendar truncated = (Calendar) date.clone();
- modify(truncated, field, false);
+ modify(truncated, field, MODIFY_TRUNCATE);
return truncated;
}
@@ -299,6 +864,7 @@
* is null
* @throws ClassCastException if the object type is not a
* Date
or Calendar
+ * @throws ArithmeticException if the year is over 280 million
*/
public static Date truncate(Object date, int field) {
if (date == null) {
@@ -312,22 +878,160 @@
throw new ClassCastException("Could not truncate " + date);
}
}
+
+ //-----------------------------------------------------------------------
+ /**
+ * Ceil this date, leaving the field specified as the most
+ * significant field.
+ *
+ * For example, if you had the datetime of 28 Mar 2002
+ * 13:45:01.231, if you passed with HOUR, it would return 28 Mar
+ * 2002 13:00:00.000. If this was passed with MONTH, it would
+ * return 1 Mar 2002 0:00:00.000.
+ *
+ * @param date the date to work with
+ * @param field the field from Calendar
+ * or SEMI_MONTH
+ * @return the rounded date
+ * @throws IllegalArgumentException if the date is null
+ * @throws ArithmeticException if the year is over 280 million
+ * @since 2.5
+ */
+ public static Date ceiling(Date date, int field) {
+ if (date == null) {
+ throw new IllegalArgumentException("The date must not be null");
+ }
+ Calendar gval = Calendar.getInstance();
+ gval.setTime(date);
+ modify(gval, field, MODIFY_CEILING);
+ return gval.getTime();
+ }
+ /**
+ * Ceil this date, leaving the field specified as the most
+ * significant field.
+ *
+ * For example, if you had the datetime of 28 Mar 2002
+ * 13:45:01.231, if you passed with HOUR, it would return 28 Mar
+ * 2002 13:00:00.000. If this was passed with MONTH, it would
+ * return 1 Mar 2002 0:00:00.000.
+ *
+ * @param date the date to work with
+ * @param field the field from Calendar
+ * or SEMI_MONTH
+ * @return the rounded date (a different object)
+ * @throws IllegalArgumentException if the date is null
+ * @throws ArithmeticException if the year is over 280 million
+ * @since 2.5
+ */
+ public static Calendar ceiling(Calendar date, int field) {
+ if (date == null) {
+ throw new IllegalArgumentException("The date must not be null");
+ }
+ Calendar ceiled = (Calendar) date.clone();
+ modify(ceiled, field, MODIFY_CEILING);
+ return ceiled;
+ }
+
+ /**
+ * Ceil this date, leaving the field specified as the most
+ * significant field.
+ *
+ * For example, if you had the datetime of 28 Mar 2002
+ * 13:45:01.231, if you passed with HOUR, it would return 28 Mar
+ * 2002 13:00:00.000. If this was passed with MONTH, it would
+ * return 1 Mar 2002 0:00:00.000.
+ *
+ * @param date the date to work with, either Date
+ * or Calendar
+ * @param field the field from Calendar
+ * or SEMI_MONTH
+ * @return the rounded date
+ * @throws IllegalArgumentException if the date
+ * is null
+ * @throws ClassCastException if the object type is not a
+ * Date
or Calendar
+ * @throws ArithmeticException if the year is over 280 million
+ * @since 2.5
+ */
+ public static Date ceiling(Object date, int field) {
+ if (date == null) {
+ throw new IllegalArgumentException("The date must not be null");
+ }
+ if (date instanceof Date) {
+ return ceiling((Date) date, field);
+ } else if (date instanceof Calendar) {
+ return ceiling((Calendar) date, field).getTime();
+ } else {
+ throw new ClassCastException("Could not find ceiling of for type: " + date.getClass());
+ }
+ }
+
//-----------------------------------------------------------------------
/**
* Internal calculation method.
*
* @param val the calendar
* @param field the field constant
- * @param round true to round, false to truncate
+ * @param modType type to truncate, round or ceiling
+ * @throws ArithmeticException if the year is over 280 million
*/
- private static void modify(Calendar val, int field, boolean round) {
+ private static void modify(Calendar val, int field, int modType) {
+ if (val.get(Calendar.YEAR) > 280000000) {
+ throw new ArithmeticException("Calendar value too large for accurate calculations");
+ }
+
+ if (field == Calendar.MILLISECOND) {
+ return;
+ }
+
+ // ----------------- Fix for LANG-59 ---------------------- START ---------------
+ // see http://issues.apache.org/jira/browse/LANG-59
+ //
+ // Manually truncate milliseconds, seconds and minutes, rather than using
+ // Calendar methods.
+
+ Date date = val.getTime();
+ long time = date.getTime();
+ boolean done = false;
+
+ // truncate milliseconds
+ int millisecs = val.get(Calendar.MILLISECOND);
+ if (MODIFY_TRUNCATE == modType || millisecs < 500) {
+ time = time - millisecs;
+ }
+ if (field == Calendar.SECOND) {
+ done = true;
+ }
+
+ // truncate seconds
+ int seconds = val.get(Calendar.SECOND);
+ if (!done && (MODIFY_TRUNCATE == modType || seconds < 30)) {
+ time = time - (seconds * 1000L);
+ }
+ if (field == Calendar.MINUTE) {
+ done = true;
+ }
+
+ // truncate minutes
+ int minutes = val.get(Calendar.MINUTE);
+ if (!done && (MODIFY_TRUNCATE == modType || minutes < 30)) {
+ time = time - (minutes * 60000L);
+ }
+
+ // reset time
+ if (date.getTime() != time) {
+ date.setTime(time);
+ val.setTime(date);
+ }
+ // ----------------- Fix for LANG-59 ----------------------- END ----------------
+
boolean roundUp = false;
for (int i = 0; i < fields.length; i++) {
for (int j = 0; j < fields[i].length; j++) {
if (fields[i][j] == field) {
//This is our field... we stop looping
- if (round && roundUp) {
+ if (modType == MODIFY_CEILING || (modType == MODIFY_ROUND && roundUp)) {
if (field == DateUtils.SEMI_MONTH) {
//This is a special case that's hard to generalize
//If the date is 1, we round up to 16, otherwise
@@ -338,6 +1042,18 @@
val.add(Calendar.DATE, -15);
val.add(Calendar.MONTH, 1);
}
+// ----------------- Fix for LANG-440 ---------------------- START ---------------
+ } else if (field == Calendar.AM_PM) {
+ // This is a special case
+ // If the time is 0, we round up to 12, otherwise
+ // we subtract 12 hours and add 1 day
+ if (val.get(Calendar.HOUR_OF_DAY) == 0) {
+ val.add(Calendar.HOUR_OF_DAY, 12);
+ } else {
+ val.add(Calendar.HOUR_OF_DAY, -12);
+ val.add(Calendar.DATE, 1);
+ }
+// ----------------- Fix for LANG-440 ---------------------- END ---------------
} else {
//We need at add one to this field since the
// last number causes us to round up
@@ -369,14 +1085,14 @@
}
break;
case Calendar.AM_PM:
- if (fields[i][0] == Calendar.HOUR) {
+ if (fields[i][0] == Calendar.HOUR_OF_DAY) {
//If we're going to drop the HOUR field's value,
// we want to do this our own way.
- offset = val.get(Calendar.HOUR);
+ offset = val.get(Calendar.HOUR_OF_DAY);
if (offset >= 12) {
offset -= 12;
}
- roundUp = offset > 6;
+ roundUp = offset >= 6;
offsetSet = true;
}
break;
@@ -390,170 +1106,60 @@
roundUp = offset > ((max - min) / 2);
}
//We need to remove this field
- val.add(fields[i][0], -offset);
+ if (offset != 0) {
+ val.set(fields[i][0], val.get(fields[i][0]) - offset);
+ }
}
throw new IllegalArgumentException("The field " + field + " is not supported");
}
- // TODO: Decide whether this code is removed or goes into 2.1
//-----------------------------------------------------------------------
- /*
- * Parses a date string formatted in CVS format.
- *
- * @param dateStr the date to parse
- * @return the parsed date
- * @throws IllegalArgumentException if the date cannot be parsed
- public static Calendar parseCVS(String dateStr) {
- if (dateStr == null) {
- throw new IllegalArgumentException("The date must not be null");
- }
- //Get the symbol names
- DateFormatSymbols symbols = new DateFormatSymbols(Locale.ENGLISH);
-
- //Prep the string to parse
- String value = dateStr.toLowerCase().trim();
-
- //Get the current date/time
- Calendar now = Calendar.getInstance();
- if (value.endsWith(" ago")) {
- //If this was a date that was "ago" the current time...
- //Strip out the ' ago' part
- value = value.substring(0, value.length() - 4);
-
- //Split the value and unit
- int start = value.indexOf(" ");
- if (start < 0) {
- throw new IllegalArgumentException("Could not find space in between value and unit");
- }
- String unit = value.substring(start + 1);
- value = value.substring(0, start);
- //We support "a week", so we need to parse the value as "a"
- int val = 0;
- if (value.equals("a") || value.equals("an")) {
- val = 1;
- } else {
- val = Integer.parseInt(value);
- }
-
- //Determine the unit
- if (unit.equals("milliseconds") || unit.equals("millisecond")) {
- now.add(Calendar.MILLISECOND, -val);
- } else if (unit.equals("seconds") || unit.equals("second")) {
- now.add(Calendar.SECOND, -val);
- } else if (unit.equals("minutes") || unit.equals("minute")) {
- now.add(Calendar.MINUTE, -val);
- } else if (unit.equals("hours") || unit.equals("hour")) {
- now.add(Calendar.HOUR, -val);
- } else if (unit.equals("days") || unit.equals("day")) {
- now.add(Calendar.DATE, -val);
- } else if (unit.equals("weeks") || unit.equals("week")) {
- now.add(Calendar.DATE, -val * 7);
- } else if (unit.equals("fortnights") || unit.equals("fortnight")) {
- now.add(Calendar.DATE, -val * 14);
- } else if (unit.equals("months") || unit.equals("month")) {
- now.add(Calendar.MONTH, -val);
- } else if (unit.equals("years") || unit.equals("year")) {
- now.add(Calendar.YEAR, -val);
- } else {
- throw new IllegalArgumentException("We do not understand that many units ago");
- }
- return now;
- } else if (value.startsWith("last ")) {
- //If this was the last time a certain field was met
- //Strip out the 'last ' part
- value = value.substring(5);
- //Get the current date/time
- String[] strings = symbols.getWeekdays();
- for (int i = 0; i < strings.length; i++) {
- if (value.equalsIgnoreCase(strings[i])) {
- //How many days after Sunday
- int daysAgo = now.get(Calendar.DAY_OF_WEEK) - i;
- if (daysAgo <= 0) {
- daysAgo += 7;
- }
- now.add(Calendar.DATE, -daysAgo);
- return now;
- }
- }
- strings = symbols.getMonths();
- for (int i = 0; i < strings.length; i++) {
- if (value.equalsIgnoreCase(strings[i])) {
- //How many days after January
- int monthsAgo = now.get(Calendar.MONTH) - i;
- if (monthsAgo <= 0) {
- monthsAgo += 12;
- }
- now.add(Calendar.MONTH, -monthsAgo);
- return now;
- }
- }
- if (value.equals("week")) {
- now.add(Calendar.DATE, -7);
- return now;
- }
- throw new IllegalArgumentException("We do not understand that last units");
- } else if (value.equals("yesterday")) {
- now.add(Calendar.DATE, -1);
- return now;
- } else if (value.equals("tomorrow")) {
- now.add(Calendar.DATE, 1);
- return now;
- }
- //Try to parse the date a number of different ways
- for (int i = 0; i < dateFormats.length; i++) {
- try {
- Date datetime = dateFormats[i].parse(dateStr);
- Calendar cal = Calendar.getInstance();
- cal.setTime(datetime);
- return cal;
- } catch (ParseException pe) {
- //we ignore this and just keep trying
- }
- }
-
- throw new IllegalArgumentException("Unable to parse '" + dateStr + "'.");
- }
- */
-
- //-----------------------------------------------------------------------
/**
- * This constructs an Iterator
that will
- * start and stop over a date range based on the focused
- * date and the range style.
+ * This constructs an Iterator
over each day in a date
+ * range defined by a focus date and range style.
*
* For instance, passing Thursday, July 4, 2002 and a
- * RANGE_MONTH_SUNDAY
will return an
- * Iterator
that starts with Sunday, June 30,
- * 2002 and ends with Saturday, August 3, 2002.
- *
- * @param focus the date to work with
- * @param rangeStyle the style constant to use. Must be one of the range
- * styles listed for the {@link #iterator(Calendar, int)} method.
+ * RANGE_MONTH_SUNDAY
will return an Iterator
+ * that starts with Sunday, June 30, 2002 and ends with Saturday, August 3,
+ * 2002, returning a Calendar instance for each intermediate day.
*
- * @return the date iterator
- * @throws IllegalArgumentException if the date is null
or if
- * the rangeStyle is not
+ * This method provides an iterator that returns Calendar objects.
+ * The days are progressed using {@link Calendar#add(int, int)}.
+ *
+ * @param focus the date to work with, not null
+ * @param rangeStyle the style constant to use. Must be one of
+ * {@link DateUtils#RANGE_MONTH_SUNDAY},
+ * {@link DateUtils#RANGE_MONTH_MONDAY},
+ * {@link DateUtils#RANGE_WEEK_SUNDAY},
+ * {@link DateUtils#RANGE_WEEK_MONDAY},
+ * {@link DateUtils#RANGE_WEEK_RELATIVE},
+ * {@link DateUtils#RANGE_WEEK_CENTER}
+ * @return the date iterator, which always returns Calendar instances
+ * @throws IllegalArgumentException if the date is null
+ * @throws IllegalArgumentException if the rangeStyle is invalid
*/
public static Iterator iterator(Date focus, int rangeStyle) {
if (focus == null) {
throw new IllegalArgumentException("The date must not be null");
}
- GregorianCalendar gval = new GregorianCalendar();
+ Calendar gval = Calendar.getInstance();
gval.setTime(focus);
return iterator(gval, rangeStyle);
}
/**
- * This constructs an Iterator
that will
- * start and stop over a date range based on the focused
- * date and the range style.
+ * This constructs an Iterator
over each day in a date
+ * range defined by a focus date and range style.
*
* For instance, passing Thursday, July 4, 2002 and a
- * RANGE_MONTH_SUNDAY
will return an
- * Iterator
that starts with Sunday, June 30,
- * 2002 and ends with Saturday, August 3, 2002.
- *
+ * RANGE_MONTH_SUNDAY
will return an Iterator
+ * that starts with Sunday, June 30, 2002 and ends with Saturday, August 3,
+ * 2002, returning a Calendar instance for each intermediate day.
+ *
+ * This method provides an iterator that returns Calendar objects.
+ * The days are progressed using {@link Calendar#add(int, int)}.
+ *
* @param focus the date to work with
* @param rangeStyle the style constant to use. Must be one of
* {@link DateUtils#RANGE_MONTH_SUNDAY},
@@ -564,6 +1170,7 @@
* {@link DateUtils#RANGE_WEEK_CENTER}
* @return the date iterator
* @throws IllegalArgumentException if the date is null
+ * @throws IllegalArgumentException if the rangeStyle is invalid
*/
public static Iterator iterator(Calendar focus, int rangeStyle) {
if (focus == null) {
@@ -638,15 +1245,14 @@
}
/**
- * This constructs an Iterator
that will
- * start and stop over a date range based on the focused
- * date and the range style.
+ * This constructs an Iterator
over each day in a date
+ * range defined by a focus date and range style.
*
* For instance, passing Thursday, July 4, 2002 and a
- * RANGE_MONTH_SUNDAY
will return an
- * Iterator
that starts with Sunday, June 30,
- * 2002 and ends with Saturday, August 3, 2002.
- *
+ * RANGE_MONTH_SUNDAY
will return an Iterator
+ * that starts with Sunday, June 30, 2002 and ends with Saturday, August 3,
+ * 2002, returning a Calendar instance for each intermediate day.
+ *
* @param focus the date to work with, either
* Date
or Calendar
* @param rangeStyle the style constant to use. Must be one of the range
@@ -669,25 +1275,620 @@
throw new ClassCastException("Could not iterate based on " + focus);
}
}
+
+ /**
+ * Returns the number of milliseconds within the
+ * fragment. All datefields greater than the fragment will be ignored.
+ *
+ * Asking the milliseconds of any date will only return the number of milliseconds
+ * of the current second (resulting in a number between 0 and 999). This
+ * method will retrieve the number of milliseconds for any fragment.
+ * For example, if you want to calculate the number of milliseconds past today,
+ * your fragment is Calendar.DATE or Calendar.DAY_OF_YEAR. The result will
+ * be all milliseconds of the past hour(s), minutes(s) and second(s).
+ *
+ * Valid fragments are: Calendar.YEAR, Calendar.MONTH, both
+ * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY,
+ * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND
+ * A fragment less than or equal to a SECOND field will return 0.
+ *
+ *
+ *
+ * - January 1, 2008 7:15:10.538 with Calendar.SECOND as fragment will return 538
+ * - January 6, 2008 7:15:10.538 with Calendar.SECOND as fragment will return 538
+ * - January 6, 2008 7:15:10.538 with Calendar.MINUTE as fragment will return 10538 (10*1000 + 538)
+ * - January 16, 2008 7:15:10.538 with Calendar.MILLISECOND as fragment will return 0
+ * (a millisecond cannot be split in milliseconds)
+ *
+ *
+ *
+ * @param date the date to work with, not null
+ * @param fragment the Calendar field part of date to calculate
+ * @return number of milliseconds within the fragment of date
+ * @throws IllegalArgumentException if the date is null
or
+ * fragment is not supported
+ * @since 2.4
+ */
+ public static long getFragmentInMilliseconds(Date date, int fragment) {
+ return getFragment(date, fragment, Calendar.MILLISECOND);
+ }
+
+ /**
+ * Returns the number of seconds within the
+ * fragment. All datefields greater than the fragment will be ignored.
+ *
+ * Asking the seconds of any date will only return the number of seconds
+ * of the current minute (resulting in a number between 0 and 59). This
+ * method will retrieve the number of seconds for any fragment.
+ * For example, if you want to calculate the number of seconds past today,
+ * your fragment is Calendar.DATE or Calendar.DAY_OF_YEAR. The result will
+ * be all seconds of the past hour(s) and minutes(s).
+ *
+ * Valid fragments are: Calendar.YEAR, Calendar.MONTH, both
+ * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY,
+ * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND
+ * A fragment less than or equal to a SECOND field will return 0.
+ *
+ *
+ *
+ * - January 1, 2008 7:15:10.538 with Calendar.MINUTE as fragment will return 10
+ * (equivalent to deprecated date.getSeconds())
+ * - January 6, 2008 7:15:10.538 with Calendar.MINUTE as fragment will return 10
+ * (equivalent to deprecated date.getSeconds())
+ * - January 6, 2008 7:15:10.538 with Calendar.DAY_OF_YEAR as fragment will return 26110
+ * (7*3600 + 15*60 + 10)
+ * - January 16, 2008 7:15:10.538 with Calendar.MILLISECOND as fragment will return 0
+ * (a millisecond cannot be split in seconds)
+ *
+ *
+ *
+ * @param date the date to work with, not null
+ * @param fragment the Calendar field part of date to calculate
+ * @return number of seconds within the fragment of date
+ * @throws IllegalArgumentException if the date is null
or
+ * fragment is not supported
+ * @since 2.4
+ */
+ public static long getFragmentInSeconds(Date date, int fragment) {
+ return getFragment(date, fragment, Calendar.SECOND);
+ }
+
+ /**
+ * Returns the number of minutes within the
+ * fragment. All datefields greater than the fragment will be ignored.
+ *
+ * Asking the minutes of any date will only return the number of minutes
+ * of the current hour (resulting in a number between 0 and 59). This
+ * method will retrieve the number of minutes for any fragment.
+ * For example, if you want to calculate the number of minutes past this month,
+ * your fragment is Calendar.MONTH. The result will be all minutes of the
+ * past day(s) and hour(s).
+ *
+ * Valid fragments are: Calendar.YEAR, Calendar.MONTH, both
+ * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY,
+ * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND
+ * A fragment less than or equal to a MINUTE field will return 0.
+ *
+ *
+ *
+ * - January 1, 2008 7:15:10.538 with Calendar.HOUR_OF_DAY as fragment will return 15
+ * (equivalent to deprecated date.getMinutes())
+ * - January 6, 2008 7:15:10.538 with Calendar.HOUR_OF_DAY as fragment will return 15
+ * (equivalent to deprecated date.getMinutes())
+ * - January 1, 2008 7:15:10.538 with Calendar.MONTH as fragment will return 15
+ * - January 6, 2008 7:15:10.538 with Calendar.MONTH as fragment will return 435 (7*60 + 15)
+ * - January 16, 2008 7:15:10.538 with Calendar.MILLISECOND as fragment will return 0
+ * (a millisecond cannot be split in minutes)
+ *
+ *
+ *
+ * @param date the date to work with, not null
+ * @param fragment the Calendar field part of date to calculate
+ * @return number of minutes within the fragment of date
+ * @throws IllegalArgumentException if the date is null
or
+ * fragment is not supported
+ * @since 2.4
+ */
+ public static long getFragmentInMinutes(Date date, int fragment) {
+ return getFragment(date, fragment, Calendar.MINUTE);
+ }
+
+ /**
+ * Returns the number of hours within the
+ * fragment. All datefields greater than the fragment will be ignored.
+ *
+ * Asking the hours of any date will only return the number of hours
+ * of the current day (resulting in a number between 0 and 23). This
+ * method will retrieve the number of hours for any fragment.
+ * For example, if you want to calculate the number of hours past this month,
+ * your fragment is Calendar.MONTH. The result will be all hours of the
+ * past day(s).
+ *
+ * Valid fragments are: Calendar.YEAR, Calendar.MONTH, both
+ * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY,
+ * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND
+ * A fragment less than or equal to a HOUR field will return 0.
+ *
+ *
+ *
+ * - January 1, 2008 7:15:10.538 with Calendar.DAY_OF_YEAR as fragment will return 7
+ * (equivalent to deprecated date.getHours())
+ * - January 6, 2008 7:15:10.538 with Calendar.DAY_OF_YEAR as fragment will return 7
+ * (equivalent to deprecated date.getHours())
+ * - January 1, 2008 7:15:10.538 with Calendar.MONTH as fragment will return 7
+ * - January 6, 2008 7:15:10.538 with Calendar.MONTH as fragment will return 127 (5*24 + 7)
+ * - January 16, 2008 7:15:10.538 with Calendar.MILLISECOND as fragment will return 0
+ * (a millisecond cannot be split in hours)
+ *
+ *
+ *
+ * @param date the date to work with, not null
+ * @param fragment the Calendar field part of date to calculate
+ * @return number of hours within the fragment of date
+ * @throws IllegalArgumentException if the date is null
or
+ * fragment is not supported
+ * @since 2.4
+ */
+ public static long getFragmentInHours(Date date, int fragment) {
+ return getFragment(date, fragment, Calendar.HOUR_OF_DAY);
+ }
+
+ /**
+ * Returns the number of days within the
+ * fragment. All datefields greater than the fragment will be ignored.
+ *
+ * Asking the days of any date will only return the number of days
+ * of the current month (resulting in a number between 1 and 31). This
+ * method will retrieve the number of days for any fragment.
+ * For example, if you want to calculate the number of days past this year,
+ * your fragment is Calendar.YEAR. The result will be all days of the
+ * past month(s).
+ *
+ * Valid fragments are: Calendar.YEAR, Calendar.MONTH, both
+ * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY,
+ * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND
+ * A fragment less than or equal to a DAY field will return 0.
+ *
+ *
+ *
+ * - January 28, 2008 with Calendar.MONTH as fragment will return 28
+ * (equivalent to deprecated date.getDay())
+ * - February 28, 2008 with Calendar.MONTH as fragment will return 28
+ * (equivalent to deprecated date.getDay())
+ * - January 28, 2008 with Calendar.YEAR as fragment will return 28
+ * - February 28, 2008 with Calendar.YEAR as fragment will return 59
+ * - January 28, 2008 with Calendar.MILLISECOND as fragment will return 0
+ * (a millisecond cannot be split in days)
+ *
+ *
+ *
+ * @param date the date to work with, not null
+ * @param fragment the Calendar field part of date to calculate
+ * @return number of days within the fragment of date
+ * @throws IllegalArgumentException if the date is null
or
+ * fragment is not supported
+ * @since 2.4
+ */
+ public static long getFragmentInDays(Date date, int fragment) {
+ return getFragment(date, fragment, Calendar.DAY_OF_YEAR);
+ }
/**
+ * Returns the number of milliseconds within the
+ * fragment. All datefields greater than the fragment will be ignored.
+ *
+ * Asking the milliseconds of any date will only return the number of milliseconds
+ * of the current second (resulting in a number between 0 and 999). This
+ * method will retrieve the number of milliseconds for any fragment.
+ * For example, if you want to calculate the number of seconds past today,
+ * your fragment is Calendar.DATE or Calendar.DAY_OF_YEAR. The result will
+ * be all seconds of the past hour(s), minutes(s) and second(s).
+ *
+ * Valid fragments are: Calendar.YEAR, Calendar.MONTH, both
+ * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY,
+ * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND
+ * A fragment less than or equal to a MILLISECOND field will return 0.
+ *
+ *
+ *
+ * - January 1, 2008 7:15:10.538 with Calendar.SECOND as fragment will return 538
+ * (equivalent to calendar.get(Calendar.MILLISECOND))
+ * - January 6, 2008 7:15:10.538 with Calendar.SECOND as fragment will return 538
+ * (equivalent to calendar.get(Calendar.MILLISECOND))
+ * - January 6, 2008 7:15:10.538 with Calendar.MINUTE as fragment will return 10538
+ * (10*1000 + 538)
+ * - January 16, 2008 7:15:10.538 with Calendar.MILLISECOND as fragment will return 0
+ * (a millisecond cannot be split in milliseconds)
+ *
+ *
+ *
+ * @param calendar the calendar to work with, not null
+ * @param fragment the Calendar field part of calendar to calculate
+ * @return number of milliseconds within the fragment of date
+ * @throws IllegalArgumentException if the date is null
or
+ * fragment is not supported
+ * @since 2.4
+ */
+ public static long getFragmentInMilliseconds(Calendar calendar, int fragment) {
+ return getFragment(calendar, fragment, Calendar.MILLISECOND);
+ }
+ /**
+ * Returns the number of seconds within the
+ * fragment. All datefields greater than the fragment will be ignored.
+ *
+ * Asking the seconds of any date will only return the number of seconds
+ * of the current minute (resulting in a number between 0 and 59). This
+ * method will retrieve the number of seconds for any fragment.
+ * For example, if you want to calculate the number of seconds past today,
+ * your fragment is Calendar.DATE or Calendar.DAY_OF_YEAR. The result will
+ * be all seconds of the past hour(s) and minutes(s).
+ *
+ * Valid fragments are: Calendar.YEAR, Calendar.MONTH, both
+ * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY,
+ * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND
+ * A fragment less than or equal to a SECOND field will return 0.
+ *
+ *
+ *
+ * - January 1, 2008 7:15:10.538 with Calendar.MINUTE as fragment will return 10
+ * (equivalent to calendar.get(Calendar.SECOND))
+ * - January 6, 2008 7:15:10.538 with Calendar.MINUTE as fragment will return 10
+ * (equivalent to calendar.get(Calendar.SECOND))
+ * - January 6, 2008 7:15:10.538 with Calendar.DAY_OF_YEAR as fragment will return 26110
+ * (7*3600 + 15*60 + 10)
+ * - January 16, 2008 7:15:10.538 with Calendar.MILLISECOND as fragment will return 0
+ * (a millisecond cannot be split in seconds)
+ *
+ *
+ *
+ * @param calendar the calendar to work with, not null
+ * @param fragment the Calendar field part of calendar to calculate
+ * @return number of seconds within the fragment of date
+ * @throws IllegalArgumentException if the date is null
or
+ * fragment is not supported
+ * @since 2.4
+ */
+ public static long getFragmentInSeconds(Calendar calendar, int fragment) {
+ return getFragment(calendar, fragment, Calendar.SECOND);
+ }
+
+ /**
+ * Returns the number of minutes within the
+ * fragment. All datefields greater than the fragment will be ignored.
+ *
+ * Asking the minutes of any date will only return the number of minutes
+ * of the current hour (resulting in a number between 0 and 59). This
+ * method will retrieve the number of minutes for any fragment.
+ * For example, if you want to calculate the number of minutes past this month,
+ * your fragment is Calendar.MONTH. The result will be all minutes of the
+ * past day(s) and hour(s).
+ *
+ * Valid fragments are: Calendar.YEAR, Calendar.MONTH, both
+ * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY,
+ * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND
+ * A fragment less than or equal to a MINUTE field will return 0.
+ *
+ *
+ *
+ * - January 1, 2008 7:15:10.538 with Calendar.HOUR_OF_DAY as fragment will return 15
+ * (equivalent to calendar.get(Calendar.MINUTES))
+ * - January 6, 2008 7:15:10.538 with Calendar.HOUR_OF_DAY as fragment will return 15
+ * (equivalent to calendar.get(Calendar.MINUTES))
+ * - January 1, 2008 7:15:10.538 with Calendar.MONTH as fragment will return 15
+ * - January 6, 2008 7:15:10.538 with Calendar.MONTH as fragment will return 435 (7*60 + 15)
+ * - January 16, 2008 7:15:10.538 with Calendar.MILLISECOND as fragment will return 0
+ * (a millisecond cannot be split in minutes)
+ *
+ *
+ *
+ * @param calendar the calendar to work with, not null
+ * @param fragment the Calendar field part of calendar to calculate
+ * @return number of minutes within the fragment of date
+ * @throws IllegalArgumentException if the date is null
or
+ * fragment is not supported
+ * @since 2.4
+ */
+ public static long getFragmentInMinutes(Calendar calendar, int fragment) {
+ return getFragment(calendar, fragment, Calendar.MINUTE);
+ }
+
+ /**
+ * Returns the number of hours within the
+ * fragment. All datefields greater than the fragment will be ignored.
+ *
+ * Asking the hours of any date will only return the number of hours
+ * of the current day (resulting in a number between 0 and 23). This
+ * method will retrieve the number of hours for any fragment.
+ * For example, if you want to calculate the number of hours past this month,
+ * your fragment is Calendar.MONTH. The result will be all hours of the
+ * past day(s).
+ *
+ * Valid fragments are: Calendar.YEAR, Calendar.MONTH, both
+ * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY,
+ * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND
+ * A fragment less than or equal to a HOUR field will return 0.
+ *
+ *
+ *
+ * - January 1, 2008 7:15:10.538 with Calendar.DAY_OF_YEAR as fragment will return 7
+ * (equivalent to calendar.get(Calendar.HOUR_OF_DAY))
+ * - January 6, 2008 7:15:10.538 with Calendar.DAY_OF_YEAR as fragment will return 7
+ * (equivalent to calendar.get(Calendar.HOUR_OF_DAY))
+ * - January 1, 2008 7:15:10.538 with Calendar.MONTH as fragment will return 7
+ * - January 6, 2008 7:15:10.538 with Calendar.MONTH as fragment will return 127 (5*24 + 7)
+ * - January 16, 2008 7:15:10.538 with Calendar.MILLISECOND as fragment will return 0
+ * (a millisecond cannot be split in hours)
+ *
+ *
+ *
+ * @param calendar the calendar to work with, not null
+ * @param fragment the Calendar field part of calendar to calculate
+ * @return number of hours within the fragment of date
+ * @throws IllegalArgumentException if the date is null
or
+ * fragment is not supported
+ * @since 2.4
+ */
+ public static long getFragmentInHours(Calendar calendar, int fragment) {
+ return getFragment(calendar, fragment, Calendar.HOUR_OF_DAY);
+ }
+
+ /**
+ * Returns the number of days within the
+ * fragment. All datefields greater than the fragment will be ignored.
+ *
+ * Asking the days of any date will only return the number of days
+ * of the current month (resulting in a number between 1 and 31). This
+ * method will retrieve the number of days for any fragment.
+ * For example, if you want to calculate the number of days past this year,
+ * your fragment is Calendar.YEAR. The result will be all days of the
+ * past month(s).
+ *
+ * Valid fragments are: Calendar.YEAR, Calendar.MONTH, both
+ * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY,
+ * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND
+ * A fragment less than or equal to a DAY field will return 0.
+ *
+ *
+ *
+ * - January 28, 2008 with Calendar.MONTH as fragment will return 28
+ * (equivalent to calendar.get(Calendar.DAY_OF_MONTH))
+ * - February 28, 2008 with Calendar.MONTH as fragment will return 28
+ * (equivalent to calendar.get(Calendar.DAY_OF_MONTH))
+ * - January 28, 2008 with Calendar.YEAR as fragment will return 28
+ * (equivalent to calendar.get(Calendar.DAY_OF_YEAR))
+ * - February 28, 2008 with Calendar.YEAR as fragment will return 59
+ * (equivalent to calendar.get(Calendar.DAY_OF_YEAR))
+ * - January 28, 2008 with Calendar.MILLISECOND as fragment will return 0
+ * (a millisecond cannot be split in days)
+ *
+ *
+ *
+ * @param calendar the calendar to work with, not null
+ * @param fragment the Calendar field part of calendar to calculate
+ * @return number of days within the fragment of date
+ * @throws IllegalArgumentException if the date is null
or
+ * fragment is not supported
+ * @since 2.4
+ */
+ public static long getFragmentInDays(Calendar calendar, int fragment) {
+ return getFragment(calendar, fragment, Calendar.DAY_OF_YEAR);
+ }
+
+ /**
+ * Date-version for fragment-calculation in any unit
+ *
+ * @param date the date to work with, not null
+ * @param fragment the Calendar field part of date to calculate
+ * @param unit Calendar field defining the unit
+ * @return number of units within the fragment of the date
+ * @throws IllegalArgumentException if the date is null
or
+ * fragment is not supported
+ * @since 2.4
+ */
+ private static long getFragment(Date date, int fragment, int unit) {
+ if(date == null) {
+ throw new IllegalArgumentException("The date must not be null");
+ }
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTime(date);
+ return getFragment(calendar, fragment, unit);
+ }
+
+ /**
+ * Calendar-version for fragment-calculation in any unit
+ *
+ * @param calendar the calendar to work with, not null
+ * @param fragment the Calendar field part of calendar to calculate
+ * @param unit Calendar field defining the unit
+ * @return number of units within the fragment of the calendar
+ * @throws IllegalArgumentException if the date is null
or
+ * fragment is not supported
+ * @since 2.4
+ */
+ private static long getFragment(Calendar calendar, int fragment, int unit) {
+ if(calendar == null) {
+ throw new IllegalArgumentException("The date must not be null");
+ }
+ long millisPerUnit = getMillisPerUnit(unit);
+ long result = 0;
+
+ // Fragments bigger than a day require a breakdown to days
+ switch (fragment) {
+ case Calendar.YEAR:
+ result += (calendar.get(Calendar.DAY_OF_YEAR) * MILLIS_PER_DAY) / millisPerUnit;
+ break;
+ case Calendar.MONTH:
+ result += (calendar.get(Calendar.DAY_OF_MONTH) * MILLIS_PER_DAY) / millisPerUnit;
+ break;
+ }
+
+ switch (fragment) {
+ // Number of days already calculated for these cases
+ case Calendar.YEAR:
+ case Calendar.MONTH:
+
+ // The rest of the valid cases
+ case Calendar.DAY_OF_YEAR:
+ case Calendar.DATE:
+ result += (calendar.get(Calendar.HOUR_OF_DAY) * MILLIS_PER_HOUR) / millisPerUnit;
+ //$FALL-THROUGH$
+ case Calendar.HOUR_OF_DAY:
+ result += (calendar.get(Calendar.MINUTE) * MILLIS_PER_MINUTE) / millisPerUnit;
+ //$FALL-THROUGH$
+ case Calendar.MINUTE:
+ result += (calendar.get(Calendar.SECOND) * MILLIS_PER_SECOND) / millisPerUnit;
+ //$FALL-THROUGH$
+ case Calendar.SECOND:
+ result += (calendar.get(Calendar.MILLISECOND) * 1) / millisPerUnit;
+ break;
+ case Calendar.MILLISECOND:
+ break;//never useful
+ default:
+ throw new IllegalArgumentException("The fragment " + fragment + " is not supported");
+ }
+ return result;
+ }
+
+ /**
+ * Determines if two calendars are equal up to no more than the specified
+ * most significant field.
+ *
+ * @param cal1 the first calendar, not null
+ * @param cal2 the second calendar, not null
+ * @param field the field from Calendar
+ * @return true
if equal; otherwise false
+ * @throws IllegalArgumentException if any argument is null
+ * @see #truncate(Calendar, int)
+ * @see #truncatedEquals(Date, Date, int)
+ * @since 2.6
+ */
+ public static boolean truncatedEquals(Calendar cal1, Calendar cal2, int field) {
+ return truncatedCompareTo(cal1, cal2, field) == 0;
+ }
+
+ /**
+ * Determines if two dates are equal up to no more than the specified
+ * most significant field.
+ *
+ * @param date1 the first date, not null
+ * @param date2 the second date, not null
+ * @param field the field from Calendar
+ * @return true
if equal; otherwise false
+ * @throws IllegalArgumentException if any argument is null
+ * @see #truncate(Date, int)
+ * @see #truncatedEquals(Calendar, Calendar, int)
+ * @since 2.6
+ */
+ public static boolean truncatedEquals(Date date1, Date date2, int field) {
+ return truncatedCompareTo(date1, date2, field) == 0;
+ }
+
+ /**
+ * Determines how two calendars compare up to no more than the specified
+ * most significant field.
+ *
+ * @param cal1 the first calendar, not null
+ * @param cal2 the second calendar, not null
+ * @param field the field from Calendar
+ * @return a negative integer, zero, or a positive integer as the first
+ * calendar is less than, equal to, or greater than the second.
+ * @throws IllegalArgumentException if any argument is null
+ * @see #truncate(Calendar, int)
+ * @see #truncatedCompareTo(Date, Date, int)
+ * @since 2.6
+ */
+ public static int truncatedCompareTo(Calendar cal1, Calendar cal2, int field) {
+ Calendar truncatedCal1 = truncate(cal1, field);
+ Calendar truncatedCal2 = truncate(cal2, field);
+ return truncatedCal1.getTime().compareTo(truncatedCal2.getTime());
+ }
+
+ /**
+ * Determines how two dates compare up to no more than the specified
+ * most significant field.
+ *
+ * @param date1 the first date, not null
+ * @param date2 the second date, not null
+ * @param field the field from Calendar
+ * @return a negative integer, zero, or a positive integer as the first
+ * date is less than, equal to, or greater than the second.
+ * @throws IllegalArgumentException if any argument is null
+ * @see #truncate(Calendar, int)
+ * @see #truncatedCompareTo(Date, Date, int)
+ * @since 2.6
+ */
+ public static int truncatedCompareTo(Date date1, Date date2, int field) {
+ Date truncatedDate1 = truncate(date1, field);
+ Date truncatedDate2 = truncate(date2, field);
+ return truncatedDate1.compareTo(truncatedDate2);
+ }
+
+ /**
+ * Returns the number of millis of a datefield, if this is a constant value
+ *
+ * @param unit A Calendar field which is a valid unit for a fragment
+ * @return number of millis
+ * @throws IllegalArgumentException if date can't be represented in millisenconds
+ * @since 2.4
+ */
+ private static long getMillisPerUnit(int unit) {
+ long result = Long.MAX_VALUE;
+ switch (unit) {
+ case Calendar.DAY_OF_YEAR:
+ case Calendar.DATE:
+ result = MILLIS_PER_DAY;
+ break;
+ case Calendar.HOUR_OF_DAY:
+ result = MILLIS_PER_HOUR;
+ break;
+ case Calendar.MINUTE:
+ result = MILLIS_PER_MINUTE;
+ break;
+ case Calendar.SECOND:
+ result = MILLIS_PER_SECOND;
+ break;
+ case Calendar.MILLISECOND:
+ result = 1;
+ break;
+ default: throw new IllegalArgumentException("The unit " + unit + " cannot be represented is milleseconds");
+ }
+ return result;
+ }
+
+ /**
* Date iterator.
*/
static class DateIterator implements Iterator {
private final Calendar endFinal;
private final Calendar spot;
+ /**
+ * Constructs a DateIterator that ranges from one date to another.
+ *
+ * @param startFinal start date (inclusive)
+ * @param endFinal end date (not inclusive)
+ */
DateIterator(Calendar startFinal, Calendar endFinal) {
super();
this.endFinal = endFinal;
spot = startFinal;
spot.add(Calendar.DATE, -1);
}
+ /**
+ * Has the iterator not reached the end date yet?
+ *
+ * @return true
if the iterator has yet to reach the end date
+ */
public boolean hasNext() {
return spot.before(endFinal);
}
+ /**
+ * Return the next calendar in the iteration
+ *
+ * @return Object calendar for the next date
+ */
public Object next() {
if (spot.equals(endFinal)) {
throw new NoSuchElementException();
@@ -696,9 +1897,44 @@
return spot.clone();
}
+ /**
+ * Always throws UnsupportedOperationException.
+ *
+ * @throws UnsupportedOperationException
+ * @see java.util.Iterator#remove()
+ */
public void remove() {
throw new UnsupportedOperationException();
}
}
-
+
+ //-------------------------------------------------------------------------
+ // Deprecated int constants
+ // TODO: Remove in 3.0
+
+ /**
+ * Number of milliseconds in a standard second.
+ *
+ * @deprecated Use MILLIS_PER_SECOND. This will be removed in Commons Lang 3.0.
+ */
+ public static final int MILLIS_IN_SECOND = 1000;
+ /**
+ * Number of milliseconds in a standard minute.
+ *
+ * @deprecated Use MILLIS_PER_MINUTE. This will be removed in Commons Lang 3.0.
+ */
+ public static final int MILLIS_IN_MINUTE = 60 * 1000;
+ /**
+ * Number of milliseconds in a standard hour.
+ *
+ * @deprecated Use MILLIS_PER_HOUR. This will be removed in Commons Lang 3.0.
+ */
+ public static final int MILLIS_IN_HOUR = 60 * 60 * 1000;
+ /**
+ * Number of milliseconds in a standard day.
+ *
+ * @deprecated Use MILLIS_PER_DAY. This will be removed in Commons Lang 3.0.
+ */
+ public static final int MILLIS_IN_DAY = 24 * 60 * 60 * 1000;
+
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/time/DurationFormatUtils.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/time/DurationFormatUtils.java (.../DurationFormatUtils.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/time/DurationFormatUtils.java (.../DurationFormatUtils.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,202 +1,666 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * .
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
*/
package org.apache.commons.lang.time;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.text.StrBuilder;
+
/**
- * Duration formatting utilites and constants.
+ * Duration formatting utilities and constants. The following table describes the tokens
+ * used in the pattern language for formatting.
+ *
+ * character duration element
+ * y years
+ * M months
+ * d days
+ * H hours
+ * m minutes
+ * s seconds
+ * S milliseconds
+ *
*
+ * @author Apache Software Foundation
* @author Apache Ant - DateUtils
* @author Stephane Bailliez
* @author Stefan Bodewig
- * @author Stephen Colebourne
* @author Gary Gregory
- * @since 2.0
+ * @since 2.1
* @version $Id$
*/
-class DurationFormatUtils {
- // TODO: Make class public once methods can fully select which fields to output
+public class DurationFormatUtils {
/**
- * Pattern used with FastDateFormat
and SimpleDateFormat
for the ISO8601
- * date time extended format used in durations.
+ * DurationFormatUtils instances should NOT be constructed in standard programming.
+ *
+ * This constructor is public to permit tools that require a JavaBean instance
+ * to operate.
+ */
+ public DurationFormatUtils() {
+ super();
+ }
+
+ /**
+ * Pattern used with FastDateFormat
and SimpleDateFormat
+ * for the ISO8601 period format used in durations.
*
* @see org.apache.commons.lang.time.FastDateFormat
* @see java.text.SimpleDateFormat
*/
public static final String ISO_EXTENDED_FORMAT_PATTERN = "'P'yyyy'Y'M'M'd'DT'H'H'm'M's.S'S'";
+ //-----------------------------------------------------------------------
/**
- * ISO8601 formatter for the date time extended format used in durations,
- * with XML Schema durations particularly in mind.
+ * Formats the time gap as a string.
*
- * This format represents the Gregorian year, month, day, hour, minute, and second components defined
- * in � 5.5.3.2 of ISO 8601, respectively. These components are ordered in their significance by their order
- * of appearance i.e. as year, month, day, hour, minute, and second.
+ * The format used is ISO8601-like:
+ * H:m:s.S.
*
- * The ISO8601 extended format PnYnMnDTnHnMnS, where nY
- * represents the number of years, nM the number of months, nD the number of days,
- * 'T' is the date/time separator, nH the number of hours, nM the number of minutes and
- * nS the number of seconds. The number of seconds can include decimal digits to arbitrary precision.
+ * @param durationMillis the duration to format
+ * @return the time as a String
+ */
+ public static String formatDurationHMS(long durationMillis) {
+ return formatDuration(durationMillis, "H:mm:ss.SSS");
+ }
+
+ /**
+ * Formats the time gap as a string.
*
- * @see #ISO_EXTENDED_FORMAT_PATTERN
- * @see http://www.w3.org/TR/xmlschema-2/#duration
+ * The format used is the ISO8601 period format.
+ *
+ * This method formats durations using the days and lower fields of the
+ * ISO format pattern, such as P7D6TH5M4.321S.
+ *
+ * @param durationMillis the duration to format
+ * @return the time as a String
*/
- public static final FastDateFormat ISO_EXTENDED_FORMAT =
- FastDateFormat.getInstance(ISO_EXTENDED_FORMAT_PATTERN);
+ public static String formatDurationISO(long durationMillis) {
+ return formatDuration(durationMillis, ISO_EXTENDED_FORMAT_PATTERN, false);
+ }
/**
- * Get the time gap as a string.
+ * Formats the time gap as a string, using the specified format, and padding with zeros and
+ * using the default timezone.
*
- * The format used is ISO8601-like:
- * hours:minutes:seconds.milliseconds.
+ * This method formats durations using the days and lower fields of the
+ * format pattern. Months and larger are not used.
*
- * @param millis the duration to format
+ * @param durationMillis the duration to format
+ * @param format the way in which to format the duration
* @return the time as a String
*/
- public static String formatISO(long millis) {
- int hours, minutes, seconds, milliseconds;
- hours = (int) (millis / DateUtils.MILLIS_IN_HOUR);
- millis = millis - (hours * DateUtils.MILLIS_IN_HOUR);
- minutes = (int) (millis / DateUtils.MILLIS_IN_MINUTE);
- millis = millis - (minutes * DateUtils.MILLIS_IN_MINUTE);
- seconds = (int) (millis / DateUtils.MILLIS_IN_SECOND);
- millis = millis - (seconds * DateUtils.MILLIS_IN_SECOND);
- milliseconds = (int) millis;
+ public static String formatDuration(long durationMillis, String format) {
+ return formatDuration(durationMillis, format, true);
+ }
- StringBuffer buf = new StringBuffer(32);
- buf.append(hours);
- buf.append(':');
- buf.append((char) (minutes / 10 + '0'));
- buf.append((char) (minutes % 10 + '0'));
- buf.append(':');
- buf.append((char) (seconds / 10 + '0'));
- buf.append((char) (seconds % 10 + '0'));
- buf.append('.');
- if (milliseconds < 10) {
- buf.append('0').append('0');
- } else if (milliseconds < 100) {
- buf.append('0');
+ /**
+ * Formats the time gap as a string, using the specified format.
+ * Padding the left hand side of numbers with zeroes is optional and
+ * the timezone may be specified.
+ *
+ * This method formats durations using the days and lower fields of the
+ * format pattern. Months and larger are not used.
+ *
+ * @param durationMillis the duration to format
+ * @param format the way in which to format the duration
+ * @param padWithZeros whether to pad the left hand side of numbers with 0's
+ * @return the time as a String
+ */
+ public static String formatDuration(long durationMillis, String format, boolean padWithZeros) {
+
+ Token[] tokens = lexx(format);
+
+ int days = 0;
+ int hours = 0;
+ int minutes = 0;
+ int seconds = 0;
+ int milliseconds = 0;
+
+ if (Token.containsTokenWithValue(tokens, d) ) {
+ days = (int) (durationMillis / DateUtils.MILLIS_PER_DAY);
+ durationMillis = durationMillis - (days * DateUtils.MILLIS_PER_DAY);
}
- buf.append(milliseconds);
- return buf.toString();
+ if (Token.containsTokenWithValue(tokens, H) ) {
+ hours = (int) (durationMillis / DateUtils.MILLIS_PER_HOUR);
+ durationMillis = durationMillis - (hours * DateUtils.MILLIS_PER_HOUR);
+ }
+ if (Token.containsTokenWithValue(tokens, m) ) {
+ minutes = (int) (durationMillis / DateUtils.MILLIS_PER_MINUTE);
+ durationMillis = durationMillis - (minutes * DateUtils.MILLIS_PER_MINUTE);
+ }
+ if (Token.containsTokenWithValue(tokens, s) ) {
+ seconds = (int) (durationMillis / DateUtils.MILLIS_PER_SECOND);
+ durationMillis = durationMillis - (seconds * DateUtils.MILLIS_PER_SECOND);
+ }
+ if (Token.containsTokenWithValue(tokens, S) ) {
+ milliseconds = (int) durationMillis;
+ }
+
+ return format(tokens, 0, 0, days, hours, minutes, seconds, milliseconds, padWithZeros);
}
/**
- * Format an elapsed time into a plurialization correct string.
- * It is limited only to report elapsed time in minutes and
- * seconds and has the following behavior.
+ * Formats an elapsed time into a plurialization correct string.
+ *
+ * This method formats durations using the days and lower fields of the
+ * format pattern. Months and larger are not used.
+ *
+ * @param durationMillis the elapsed time to report in milliseconds
+ * @param suppressLeadingZeroElements suppresses leading 0 elements
+ * @param suppressTrailingZeroElements suppresses trailing 0 elements
+ * @return the formatted text in days/hours/minutes/seconds
+ */
+ public static String formatDurationWords(
+ long durationMillis,
+ boolean suppressLeadingZeroElements,
+ boolean suppressTrailingZeroElements) {
+
+ // This method is generally replacable by the format method, but
+ // there are a series of tweaks and special cases that require
+ // trickery to replicate.
+ String duration = formatDuration(durationMillis, "d' days 'H' hours 'm' minutes 's' seconds'");
+ if (suppressLeadingZeroElements) {
+ // this is a temporary marker on the front. Like ^ in regexp.
+ duration = " " + duration;
+ String tmp = StringUtils.replaceOnce(duration, " 0 days", "");
+ if (tmp.length() != duration.length()) {
+ duration = tmp;
+ tmp = StringUtils.replaceOnce(duration, " 0 hours", "");
+ if (tmp.length() != duration.length()) {
+ duration = tmp;
+ tmp = StringUtils.replaceOnce(duration, " 0 minutes", "");
+ duration = tmp;
+ if (tmp.length() != duration.length()) {
+ duration = StringUtils.replaceOnce(tmp, " 0 seconds", "");
+ }
+ }
+ }
+ if (duration.length() != 0) {
+ // strip the space off again
+ duration = duration.substring(1);
+ }
+ }
+ if (suppressTrailingZeroElements) {
+ String tmp = StringUtils.replaceOnce(duration, " 0 seconds", "");
+ if (tmp.length() != duration.length()) {
+ duration = tmp;
+ tmp = StringUtils.replaceOnce(duration, " 0 minutes", "");
+ if (tmp.length() != duration.length()) {
+ duration = tmp;
+ tmp = StringUtils.replaceOnce(duration, " 0 hours", "");
+ if (tmp.length() != duration.length()) {
+ duration = StringUtils.replaceOnce(tmp, " 0 days", "");
+ }
+ }
+ }
+ }
+ // handle plurals
+ duration = " " + duration;
+ duration = StringUtils.replaceOnce(duration, " 1 seconds", " 1 second");
+ duration = StringUtils.replaceOnce(duration, " 1 minutes", " 1 minute");
+ duration = StringUtils.replaceOnce(duration, " 1 hours", " 1 hour");
+ duration = StringUtils.replaceOnce(duration, " 1 days", " 1 day");
+ return duration.trim();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Formats the time gap as a string.
+ *
+ * The format used is the ISO8601 period format.
+ *
+ * @param startMillis the start of the duration to format
+ * @param endMillis the end of the duration to format
+ * @return the time as a String
+ */
+ public static String formatPeriodISO(long startMillis, long endMillis) {
+ return formatPeriod(startMillis, endMillis, ISO_EXTENDED_FORMAT_PATTERN, false, TimeZone.getDefault());
+ }
+
+ /**
+ * Formats the time gap as a string, using the specified format.
+ * Padding the left hand side of numbers with zeroes is optional.
+ *
+ * @param startMillis the start of the duration
+ * @param endMillis the end of the duration
+ * @param format the way in which to format the duration
+ * @return the time as a String
+ */
+ public static String formatPeriod(long startMillis, long endMillis, String format) {
+ return formatPeriod(startMillis, endMillis, format, true, TimeZone.getDefault());
+ }
+
+ /**
+ *
Formats the time gap as a string, using the specified format.
+ * Padding the left hand side of numbers with zeroes is optional and
+ * the timezone may be specified.
*
- *
- * - minutes are not displayed when
0
(ie:
- * "45 seconds") .
- * - seconds are always displayed in plural form (ie
- * "0 seconds" or "10 seconds") except
- * for
1
(ie "1 second")
- *
+ * When calculating the difference between months/days, it chooses to
+ * calculate months first. So when working out the number of months and
+ * days between January 15th and March 10th, it choose 1 month and
+ * 23 days gained by choosing January->February = 1 month and then
+ * calculating days forwards, and not the 1 month and 26 days gained by
+ * choosing March -> February = 1 month and then calculating days
+ * backwards.
+ *
+ * For more control, the Joda-Time
+ * library is recommended.
*
- * @param millis the elapsed time to report in milliseconds
- * @return the formatted text in minutes/seconds
+ * @param startMillis the start of the duration
+ * @param endMillis the end of the duration
+ * @param format the way in which to format the duration
+ * @param padWithZeros whether to pad the left hand side of numbers with 0's
+ * @param timezone the millis are defined in
+ * @return the time as a String
*/
- public static String formatWords(
- long millis,
- boolean supressLeadingZeroElements,
- boolean supressTrailingZeroElements) {
- long[] values = new long[4];
- values[0] = millis / DateUtils.MILLIS_IN_DAY;
- values[1] = (millis / DateUtils.MILLIS_IN_HOUR) % 24;
- values[2] = (millis / DateUtils.MILLIS_IN_MINUTE) % 60;
- values[3] = (millis / DateUtils.MILLIS_IN_SECOND) % 60;
- String[] fieldsOne = { " day ", " hour ", " minute ", " second" };
- String[] fieldsPlural = { " days ", " hours ", " minutes ", " seconds" };
+ public static String formatPeriod(long startMillis, long endMillis, String format, boolean padWithZeros,
+ TimeZone timezone) {
- StringBuffer buf = new StringBuffer(64);
- boolean valueOutput = false;
+ // Used to optimise for differences under 28 days and
+ // called formatDuration(millis, format); however this did not work
+ // over leap years.
+ // TODO: Compare performance to see if anything was lost by
+ // losing this optimisation.
+
+ Token[] tokens = lexx(format);
- for (int i = 0; i < 4; i++) {
- long value = values[i];
- if (value == 0) {
- // handle zero
- if (valueOutput) {
- if (supressTrailingZeroElements == false) {
- buf.append('0').append(fieldsPlural[i]);
+ // timezones get funky around 0, so normalizing everything to GMT
+ // stops the hours being off
+ Calendar start = Calendar.getInstance(timezone);
+ start.setTime(new Date(startMillis));
+ Calendar end = Calendar.getInstance(timezone);
+ end.setTime(new Date(endMillis));
+
+ // initial estimates
+ int milliseconds = end.get(Calendar.MILLISECOND) - start.get(Calendar.MILLISECOND);
+ int seconds = end.get(Calendar.SECOND) - start.get(Calendar.SECOND);
+ int minutes = end.get(Calendar.MINUTE) - start.get(Calendar.MINUTE);
+ int hours = end.get(Calendar.HOUR_OF_DAY) - start.get(Calendar.HOUR_OF_DAY);
+ int days = end.get(Calendar.DAY_OF_MONTH) - start.get(Calendar.DAY_OF_MONTH);
+ int months = end.get(Calendar.MONTH) - start.get(Calendar.MONTH);
+ int years = end.get(Calendar.YEAR) - start.get(Calendar.YEAR);
+
+ // each initial estimate is adjusted in case it is under 0
+ while (milliseconds < 0) {
+ milliseconds += 1000;
+ seconds -= 1;
+ }
+ while (seconds < 0) {
+ seconds += 60;
+ minutes -= 1;
+ }
+ while (minutes < 0) {
+ minutes += 60;
+ hours -= 1;
+ }
+ while (hours < 0) {
+ hours += 24;
+ days -= 1;
+ }
+
+ if (Token.containsTokenWithValue(tokens, M)) {
+ while (days < 0) {
+ days += start.getActualMaximum(Calendar.DAY_OF_MONTH);
+ months -= 1;
+ start.add(Calendar.MONTH, 1);
+ }
+
+ while (months < 0) {
+ months += 12;
+ years -= 1;
+ }
+
+ if (!Token.containsTokenWithValue(tokens, y) && years != 0) {
+ while (years != 0) {
+ months += 12 * years;
+ years = 0;
+ }
+ }
+ } else {
+ // there are no M's in the format string
+
+ if( !Token.containsTokenWithValue(tokens, y) ) {
+ int target = end.get(Calendar.YEAR);
+ if (months < 0) {
+ // target is end-year -1
+ target -= 1;
+ }
+
+ while ( (start.get(Calendar.YEAR) != target)) {
+ days += start.getActualMaximum(Calendar.DAY_OF_YEAR) - start.get(Calendar.DAY_OF_YEAR);
+
+ // Not sure I grok why this is needed, but the brutal tests show it is
+ if(start instanceof GregorianCalendar) {
+ if( (start.get(Calendar.MONTH) == Calendar.FEBRUARY) &&
+ (start.get(Calendar.DAY_OF_MONTH) == 29 ) )
+ {
+ days += 1;
+ }
}
- } else {
- if (supressLeadingZeroElements == false) {
- buf.append('0').append(fieldsPlural[i]);
- }
+
+ start.add(Calendar.YEAR, 1);
+
+ days += start.get(Calendar.DAY_OF_YEAR);
}
- } else if (value == 1) {
- // one
- valueOutput = true;
- buf.append('1').append(fieldsOne[i]);
- } else {
- // other
- valueOutput = true;
- buf.append(value).append(fieldsPlural[i]);
+
+ years = 0;
}
+
+ while( start.get(Calendar.MONTH) != end.get(Calendar.MONTH) ) {
+ days += start.getActualMaximum(Calendar.DAY_OF_MONTH);
+ start.add(Calendar.MONTH, 1);
+ }
+
+ months = 0;
+
+ while (days < 0) {
+ days += start.getActualMaximum(Calendar.DAY_OF_MONTH);
+ months -= 1;
+ start.add(Calendar.MONTH, 1);
+ }
+
}
- return buf.toString().trim();
+ // The rest of this code adds in values that
+ // aren't requested. This allows the user to ask for the
+ // number of months and get the real count and not just 0->11.
+
+ if (!Token.containsTokenWithValue(tokens, d)) {
+ hours += 24 * days;
+ days = 0;
+ }
+ if (!Token.containsTokenWithValue(tokens, H)) {
+ minutes += 60 * hours;
+ hours = 0;
+ }
+ if (!Token.containsTokenWithValue(tokens, m)) {
+ seconds += 60 * minutes;
+ minutes = 0;
+ }
+ if (!Token.containsTokenWithValue(tokens, s)) {
+ milliseconds += 1000 * seconds;
+ seconds = 0;
+ }
+
+ return format(tokens, years, months, days, hours, minutes, seconds, milliseconds, padWithZeros);
}
+ //-----------------------------------------------------------------------
/**
- * DurationFormatUtils instances should NOT be constructed in standard programming.
+ * The internal method to do the formatting.
+ *
+ * @param tokens the tokens
+ * @param years the number of years
+ * @param months the number of months
+ * @param days the number of days
+ * @param hours the number of hours
+ * @param minutes the number of minutes
+ * @param seconds the number of seconds
+ * @param milliseconds the number of millis
+ * @param padWithZeros whether to pad
+ * @return the formatted string
+ */
+ static String format(Token[] tokens, int years, int months, int days, int hours, int minutes, int seconds,
+ int milliseconds, boolean padWithZeros) {
+ StrBuilder buffer = new StrBuilder();
+ boolean lastOutputSeconds = false;
+ int sz = tokens.length;
+ for (int i = 0; i < sz; i++) {
+ Token token = tokens[i];
+ Object value = token.getValue();
+ int count = token.getCount();
+ if (value instanceof StringBuffer) {
+ buffer.append(value.toString());
+ } else {
+ if (value == y) {
+ buffer.append(padWithZeros ? StringUtils.leftPad(Integer.toString(years), count, '0') : Integer
+ .toString(years));
+ lastOutputSeconds = false;
+ } else if (value == M) {
+ buffer.append(padWithZeros ? StringUtils.leftPad(Integer.toString(months), count, '0') : Integer
+ .toString(months));
+ lastOutputSeconds = false;
+ } else if (value == d) {
+ buffer.append(padWithZeros ? StringUtils.leftPad(Integer.toString(days), count, '0') : Integer
+ .toString(days));
+ lastOutputSeconds = false;
+ } else if (value == H) {
+ buffer.append(padWithZeros ? StringUtils.leftPad(Integer.toString(hours), count, '0') : Integer
+ .toString(hours));
+ lastOutputSeconds = false;
+ } else if (value == m) {
+ buffer.append(padWithZeros ? StringUtils.leftPad(Integer.toString(minutes), count, '0') : Integer
+ .toString(minutes));
+ lastOutputSeconds = false;
+ } else if (value == s) {
+ buffer.append(padWithZeros ? StringUtils.leftPad(Integer.toString(seconds), count, '0') : Integer
+ .toString(seconds));
+ lastOutputSeconds = true;
+ } else if (value == S) {
+ if (lastOutputSeconds) {
+ milliseconds += 1000;
+ String str = padWithZeros
+ ? StringUtils.leftPad(Integer.toString(milliseconds), count, '0')
+ : Integer.toString(milliseconds);
+ buffer.append(str.substring(1));
+ } else {
+ buffer.append(padWithZeros
+ ? StringUtils.leftPad(Integer.toString(milliseconds), count, '0')
+ : Integer.toString(milliseconds));
+ }
+ lastOutputSeconds = false;
+ }
+ }
+ }
+ return buffer.toString();
+ }
+
+ static final Object y = "y";
+ static final Object M = "M";
+ static final Object d = "d";
+ static final Object H = "H";
+ static final Object m = "m";
+ static final Object s = "s";
+ static final Object S = "S";
+
+ /**
+ * Parses a classic date format string into Tokens
*
- * This constructor is public to permit tools that require a JavaBean instance
- * to operate.
+ * @param format to parse
+ * @return array of Token[]
*/
- public DurationFormatUtils() {
+ static Token[] lexx(String format) {
+ char[] array = format.toCharArray();
+ ArrayList list = new ArrayList(array.length);
+
+ boolean inLiteral = false;
+ StringBuffer buffer = null;
+ Token previous = null;
+ int sz = array.length;
+ for(int i=0; itrue
if contained
+ */
+ static boolean containsTokenWithValue(Token[] tokens, Object value) {
+ int sz = tokens.length;
+ for (int i = 0; i < sz; i++) {
+ if (tokens[i].getValue() == value) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private Object value;
+ private int count;
+
+ /**
+ * Wraps a token around a value. A value would be something like a 'Y'.
+ *
+ * @param value to wrap
+ */
+ Token(Object value) {
+ this.value = value;
+ this.count = 1;
+ }
+
+ /**
+ * Wraps a token around a repeated number of a value, for example it would
+ * store 'yyyy' as a value for y and a count of 4.
+ *
+ * @param value to wrap
+ * @param count to wrap
+ */
+ Token(Object value, int count) {
+ this.value = value;
+ this.count = count;
+ }
+
+ /**
+ * Adds another one of the value
+ */
+ void increment() {
+ count++;
+ }
+
+ /**
+ * Gets the current number of values represented
+ *
+ * @return int number of values represented
+ */
+ int getCount() {
+ return count;
+ }
+
+ /**
+ * Gets the particular value this token represents.
+ *
+ * @return Object value
+ */
+ Object getValue() {
+ return value;
+ }
+
+ /**
+ * Supports equality of this Token to another Token.
+ *
+ * @param obj2 Object to consider equality of
+ * @return boolean true
if equal
+ */
+ public boolean equals(Object obj2) {
+ if (obj2 instanceof Token) {
+ Token tok2 = (Token) obj2;
+ if (this.value.getClass() != tok2.value.getClass()) {
+ return false;
+ }
+ if (this.count != tok2.count) {
+ return false;
+ }
+ if (this.value instanceof StringBuffer) {
+ return this.value.toString().equals(tok2.value.toString());
+ } else if (this.value instanceof Number) {
+ return this.value.equals(tok2.value);
+ } else {
+ return this.value == tok2.value;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns a hashcode for the token equal to the
+ * hashcode for the token's value. Thus 'TT' and 'TTTT'
+ * will have the same hashcode.
+ *
+ * @return The hashcode for the token
+ */
+ public int hashCode() {
+ return this.value.hashCode();
+ }
+
+ /**
+ * Represents this token as a String.
+ *
+ * @return String representation of the token
+ */
+ public String toString() {
+ return StringUtils.repeat(this.value.toString(), this.count);
+ }
+ }
+
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/time/FastDateFormat.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/time/FastDateFormat.java (.../FastDateFormat.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/time/FastDateFormat.java (.../FastDateFormat.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,58 +1,23 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * FastDateFormat is a fast and thread-safe version of * {@link java.text.SimpleDateFormat}.
@@ -89,14 +57,15 @@ * *In addition, the pattern 'ZZ'
has been made to represent
* ISO8601 full format time zones (eg. +08:00
or -11:00
).
- * This introduces a minor incompatability with Java 1.4, but at a gain of
+ * This introduces a minor incompatibility with Java 1.4, but at a gain of
* useful functionality.
Gets a date formatter instance using the specified style in the + * default time zone and locale.
+ * + * @param style date style: FULL, LONG, MEDIUM, or SHORT + * @return a localized standard date formatter + * @throws IllegalArgumentException if the Locale has no date + * pattern defined + * @since 2.1 + */ + public static FastDateFormat getDateInstance(int style) { + return getDateInstance(style, null, null); + } + + /** + *Gets a date formatter instance using the specified style and + * locale in the default time zone.
+ * + * @param style date style: FULL, LONG, MEDIUM, or SHORT + * @param locale optional locale, overrides system locale + * @return a localized standard date formatter + * @throws IllegalArgumentException if the Locale has no date + * pattern defined + * @since 2.1 + */ + public static FastDateFormat getDateInstance(int style, Locale locale) { + return getDateInstance(style, null, locale); + } + + /** + *Gets a date formatter instance using the specified style and + * time zone in the default locale.
+ * + * @param style date style: FULL, LONG, MEDIUM, or SHORT + * @param timeZone optional time zone, overrides time zone of + * formatted date + * @return a localized standard date formatter + * @throws IllegalArgumentException if the Locale has no date + * pattern defined + * @since 2.1 + */ + public static FastDateFormat getDateInstance(int style, TimeZone timeZone) { + return getDateInstance(style, timeZone, null); + } + /** *Gets a date formatter instance using the specified style, time * zone and locale.
* @@ -264,16 +282,15 @@ if (timeZone != null) { key = new Pair(key, timeZone); } + if (locale == null) { - key = new Pair(key, locale); + locale = Locale.getDefault(); } + key = new Pair(key, locale); + FastDateFormat format = (FastDateFormat) cDateInstanceCache.get(key); if (format == null) { - if (locale == null) { - locale = Locale.getDefault(); - } - try { SimpleDateFormat formatter = (SimpleDateFormat) DateFormat.getDateInstance(style, locale); String pattern = formatter.toPattern(); @@ -287,7 +304,53 @@ return format; } + //----------------------------------------------------------------------- /** + *Gets a time formatter instance using the specified style in the + * default time zone and locale.
+ * + * @param style time style: FULL, LONG, MEDIUM, or SHORT + * @return a localized standard time formatter + * @throws IllegalArgumentException if the Locale has no time + * pattern defined + * @since 2.1 + */ + public static FastDateFormat getTimeInstance(int style) { + return getTimeInstance(style, null, null); + } + + /** + *Gets a time formatter instance using the specified style and + * locale in the default time zone.
+ * + * @param style time style: FULL, LONG, MEDIUM, or SHORT + * @param locale optional locale, overrides system locale + * @return a localized standard time formatter + * @throws IllegalArgumentException if the Locale has no time + * pattern defined + * @since 2.1 + */ + public static FastDateFormat getTimeInstance(int style, Locale locale) { + return getTimeInstance(style, null, locale); + } + + /** + *Gets a time formatter instance using the specified style and + * time zone in the default locale.
+ * + * @param style time style: FULL, LONG, MEDIUM, or SHORT + * @param timeZone optional time zone, overrides time zone of + * formatted time + * @return a localized standard time formatter + * @throws IllegalArgumentException if the Locale has no time + * pattern defined + * @since 2.1 + */ + public static FastDateFormat getTimeInstance(int style, TimeZone timeZone) { + return getTimeInstance(style, timeZone, null); + } + + /** *Gets a time formatter instance using the specified style, time * zone and locale.
* @@ -327,7 +390,58 @@ return format; } + //----------------------------------------------------------------------- /** + *Gets a date/time formatter instance using the specified style + * in the default time zone and locale.
+ * + * @param dateStyle date style: FULL, LONG, MEDIUM, or SHORT + * @param timeStyle time style: FULL, LONG, MEDIUM, or SHORT + * @return a localized standard date/time formatter + * @throws IllegalArgumentException if the Locale has no date/time + * pattern defined + * @since 2.1 + */ + public static FastDateFormat getDateTimeInstance( + int dateStyle, int timeStyle) { + return getDateTimeInstance(dateStyle, timeStyle, null, null); + } + + /** + *Gets a date/time formatter instance using the specified style and + * locale in the default time zone.
+ * + * @param dateStyle date style: FULL, LONG, MEDIUM, or SHORT + * @param timeStyle time style: FULL, LONG, MEDIUM, or SHORT + * @param locale optional locale, overrides system locale + * @return a localized standard date/time formatter + * @throws IllegalArgumentException if the Locale has no date/time + * pattern defined + * @since 2.1 + */ + public static FastDateFormat getDateTimeInstance( + int dateStyle, int timeStyle, Locale locale) { + return getDateTimeInstance(dateStyle, timeStyle, null, locale); + } + + /** + *Gets a date/time formatter instance using the specified style and + * time zone in the default locale.
+ * + * @param dateStyle date style: FULL, LONG, MEDIUM, or SHORT + * @param timeStyle time style: FULL, LONG, MEDIUM, or SHORT + * @param timeZone optional time zone, overrides time zone of + * formatted date + * @return a localized standard date/time formatter + * @throws IllegalArgumentException if the Locale has no date/time + * pattern defined + * @since 2.1 + */ + public static FastDateFormat getDateTimeInstance( + int dateStyle, int timeStyle, TimeZone timeZone) { + return getDateTimeInstance(dateStyle, timeStyle, timeZone, null); + } + /** *Gets a date/time formatter instance using the specified style, * time zone and locale.
* @@ -340,29 +454,27 @@ * @throws IllegalArgumentException if the Locale has no date/time * pattern defined */ - public static synchronized FastDateFormat getDateTimeInstance( - int dateStyle, int timeStyle, TimeZone timeZone, Locale locale) { + public static synchronized FastDateFormat getDateTimeInstance(int dateStyle, int timeStyle, TimeZone timeZone, + Locale locale) { Object key = new Pair(new Integer(dateStyle), new Integer(timeStyle)); if (timeZone != null) { key = new Pair(key, timeZone); } - if (locale != null) { - key = new Pair(key, locale); + if (locale == null) { + locale = Locale.getDefault(); } + key = new Pair(key, locale); FastDateFormat format = (FastDateFormat) cDateTimeInstanceCache.get(key); if (format == null) { - if (locale == null) { - locale = Locale.getDefault(); - } - try { - SimpleDateFormat formatter = (SimpleDateFormat) DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale); + SimpleDateFormat formatter = (SimpleDateFormat) DateFormat.getDateTimeInstance(dateStyle, timeStyle, + locale); String pattern = formatter.toPattern(); format = getInstance(pattern, timeZone, locale); cDateTimeInstanceCache.put(key, format); - + } catch (ClassCastException ex) { throw new IllegalArgumentException("No date time pattern for locale: " + locale); } @@ -440,7 +552,7 @@ } /** - *Initialise the instance for first use.
+ *Initializes the instance for first use.
*/ protected void init() { List rulesList = parsePattern(); @@ -495,7 +607,7 @@ break; case 'y': // year (number) if (tokenLen >= 4) { - rule = UnpaddedNumberField.INSTANCE_YEAR; + rule = selectNumberRule(Calendar.YEAR, tokenLen); } else { rule = TwoDigitYearField.INSTANCE; } @@ -593,7 +705,7 @@ * @return parsed token */ protected String parseToken(String pattern, int[] indexRef) { - StringBuffer buf = new StringBuffer(); + StrBuilder buf = new StrBuilder(); int i = indexRef[0]; int length = pattern.length(); @@ -665,8 +777,8 @@ // Format methods //----------------------------------------------------------------------- /** - *Format either a Date
or a
- * Calendar
object.
Formats a Date
, Calendar
or
+ * Long
(milliseconds) object.
Formats a millisecond long
value.
Formats a Date
object.
Formats a milliseond long
value into the
+ * supplied StringBuffer
.
Formats a Date
object into the
* supplied StringBuffer
.
Parsing not supported.
+ *Parsing is not supported.
* * @param source the string to parse * @param pos the parsing position @@ -814,7 +953,7 @@ } /** - *Gets an estimate for the maximum string length that the + *
Gets an estimate for the maximum string length that the * formatter will produce.
* *The actual formatted length will almost always be less than or @@ -829,7 +968,7 @@ // Basics //----------------------------------------------------------------------- /** - *
Compare two objects for equality.
+ *Compares two objects for equality.
* * @param obj the object to compare to * @returntrue
if equal
@@ -852,9 +991,9 @@
}
/**
- * A suitable hashcode.
+ *Returns a hashcode compatible with equals.
* - * @return a hashcode compatable with equals + * @return a hashcode compatible with equals */ public int hashCode() { int total = 0; @@ -874,21 +1013,54 @@ public String toString() { return "FastDateFormat[" + mPattern + "]"; } + + // Serializing + //----------------------------------------------------------------------- + /** + * Create the object after serialization. This implementation reinitializes the + * transient properties. + * + * @param in ObjectInputStream from which the object is being deserialized. + * @throws IOException if there is an IO issue. + * @throws ClassNotFoundException if a class cannot be found. + */ + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + init(); + } // Rules //----------------------------------------------------------------------- /** *Inner class defining a rule.
*/ private interface Rule { + /** + * Returns the estimated lentgh of the result. + * + * @return the estimated length + */ int estimateLength(); + + /** + * Appends the value of the specified calendar to the output buffer based on the rule implementation. + * + * @param buffer the output buffer + * @param calendar calendar to be appended + */ void appendTo(StringBuffer buffer, Calendar calendar); } /** *Inner class defining a numeric rule.
*/ private interface NumberRule extends Rule { + /** + * Appends the specified value to the output buffer based on the rule implementation. + * + * @param buffer the output buffer + * @param value the value to be appended + */ void appendTo(StringBuffer buffer, int value); } @@ -898,14 +1070,26 @@ private static class CharacterLiteral implements Rule { private final char mValue; + /** + * Constructs a new instance ofCharacterLiteral
+ * to hold the specified value.
+ *
+ * @param value the character literal
+ */
CharacterLiteral(char value) {
mValue = value;
}
+ /**
+ * {@inheritDoc}
+ */
public int estimateLength() {
return 1;
}
+ /**
+ * {@inheritDoc}
+ */
public void appendTo(StringBuffer buffer, Calendar calendar) {
buffer.append(mValue);
}
@@ -917,14 +1101,26 @@
private static class StringLiteral implements Rule {
private final String mValue;
+ /**
+ * Constructs a new instance of StringLiteral
+ * to hold the specified value.
+ *
+ * @param value the string literal
+ */
StringLiteral(String value) {
mValue = value;
}
+ /**
+ * {@inheritDoc}
+ */
public int estimateLength() {
return mValue.length();
}
+ /**
+ * {@inheritDoc}
+ */
public void appendTo(StringBuffer buffer, Calendar calendar) {
buffer.append(mValue);
}
@@ -937,11 +1133,21 @@
private final int mField;
private final String[] mValues;
+ /**
+ * Constructs an instance of TextField
+ * with the specified field and values.
+ *
+ * @param field the field
+ * @param values the field values
+ */
TextField(int field, String[] values) {
mField = field;
mValues = values;
}
+ /**
+ * {@inheritDoc}
+ */
public int estimateLength() {
int max = 0;
for (int i=mValues.length; --i >= 0; ) {
@@ -953,6 +1159,9 @@
return max;
}
+ /**
+ * {@inheritDoc}
+ */
public void appendTo(StringBuffer buffer, Calendar calendar) {
buffer.append(mValues[calendar.get(mField)]);
}
@@ -962,22 +1171,34 @@
* Inner class to output an unpadded number.
*/ private static class UnpaddedNumberField implements NumberRule { - static final UnpaddedNumberField INSTANCE_YEAR = new UnpaddedNumberField(Calendar.YEAR); - private final int mField; + /** + * Constructs an instance ofUnpadedNumberField
with the specified field.
+ *
+ * @param field the field
+ */
UnpaddedNumberField(int field) {
mField = field;
}
+ /**
+ * {@inheritDoc}
+ */
public int estimateLength() {
return 4;
}
+ /**
+ * {@inheritDoc}
+ */
public void appendTo(StringBuffer buffer, Calendar calendar) {
appendTo(buffer, calendar.get(mField));
}
+ /**
+ * {@inheritDoc}
+ */
public final void appendTo(StringBuffer buffer, int value) {
if (value < 10) {
buffer.append((char)(value + '0'));
@@ -995,18 +1216,32 @@
*/
private static class UnpaddedMonthField implements NumberRule {
static final UnpaddedMonthField INSTANCE = new UnpaddedMonthField();
-
+
+ /**
+ * Constructs an instance of UnpaddedMonthField
.
+ *
+ */
UnpaddedMonthField() {
+ super();
}
+ /**
+ * {@inheritDoc}
+ */
public int estimateLength() {
return 2;
}
+ /**
+ * {@inheritDoc}
+ */
public void appendTo(StringBuffer buffer, Calendar calendar) {
appendTo(buffer, calendar.get(Calendar.MONTH) + 1);
}
+ /**
+ * {@inheritDoc}
+ */
public final void appendTo(StringBuffer buffer, int value) {
if (value < 10) {
buffer.append((char)(value + '0'));
@@ -1024,6 +1259,12 @@
private final int mField;
private final int mSize;
+ /**
+ * Constructs an instance of PaddedNumberField
.
+ *
+ * @param field the field
+ * @param size size of the output field
+ */
PaddedNumberField(int field, int size) {
if (size < 3) {
// Should use UnpaddedNumberField or TwoDigitNumberField.
@@ -1033,14 +1274,23 @@
mSize = size;
}
+ /**
+ * {@inheritDoc}
+ */
public int estimateLength() {
return 4;
}
+ /**
+ * {@inheritDoc}
+ */
public void appendTo(StringBuffer buffer, Calendar calendar) {
appendTo(buffer, calendar.get(mField));
}
+ /**
+ * {@inheritDoc}
+ */
public final void appendTo(StringBuffer buffer, int value) {
if (value < 100) {
for (int i = mSize; --i >= 2; ) {
@@ -1053,7 +1303,8 @@
if (value < 1000) {
digits = 3;
} else {
- digits = (int)(Math.log(value) / LOG_10) + 1;
+ Validate.isTrue(value > -1, "Negative values should not be possible", value);
+ digits = Integer.toString(value).length();
}
for (int i = mSize; --i >= digits; ) {
buffer.append('0');
@@ -1069,18 +1320,32 @@
private static class TwoDigitNumberField implements NumberRule {
private final int mField;
+ /**
+ * Constructs an instance of TwoDigitNumberField
with the specified field.
+ *
+ * @param field the field
+ */
TwoDigitNumberField(int field) {
mField = field;
}
+ /**
+ * {@inheritDoc}
+ */
public int estimateLength() {
return 2;
}
+ /**
+ * {@inheritDoc}
+ */
public void appendTo(StringBuffer buffer, Calendar calendar) {
appendTo(buffer, calendar.get(mField));
}
+ /**
+ * {@inheritDoc}
+ */
public final void appendTo(StringBuffer buffer, int value) {
if (value < 100) {
buffer.append((char)(value / 10 + '0'));
@@ -1096,18 +1361,31 @@
*/
private static class TwoDigitYearField implements NumberRule {
static final TwoDigitYearField INSTANCE = new TwoDigitYearField();
-
+
+ /**
+ * Constructs an instance of TwoDigitYearField
.
+ */
TwoDigitYearField() {
+ super();
}
+ /**
+ * {@inheritDoc}
+ */
public int estimateLength() {
return 2;
}
+ /**
+ * {@inheritDoc}
+ */
public void appendTo(StringBuffer buffer, Calendar calendar) {
appendTo(buffer, calendar.get(Calendar.YEAR) % 100);
}
+ /**
+ * {@inheritDoc}
+ */
public final void appendTo(StringBuffer buffer, int value) {
buffer.append((char)(value / 10 + '0'));
buffer.append((char)(value % 10 + '0'));
@@ -1119,18 +1397,31 @@
*/
private static class TwoDigitMonthField implements NumberRule {
static final TwoDigitMonthField INSTANCE = new TwoDigitMonthField();
-
+
+ /**
+ * Constructs an instance of TwoDigitMonthField
.
+ */
TwoDigitMonthField() {
+ super();
}
+ /**
+ * {@inheritDoc}
+ */
public int estimateLength() {
return 2;
}
+ /**
+ * {@inheritDoc}
+ */
public void appendTo(StringBuffer buffer, Calendar calendar) {
appendTo(buffer, calendar.get(Calendar.MONTH) + 1);
}
+ /**
+ * {@inheritDoc}
+ */
public final void appendTo(StringBuffer buffer, int value) {
buffer.append((char)(value / 10 + '0'));
buffer.append((char)(value % 10 + '0'));
@@ -1143,14 +1434,26 @@
private static class TwelveHourField implements NumberRule {
private final NumberRule mRule;
+ /**
+ * Constructs an instance of TwelveHourField
with the specified
+ * NumberRule
.
+ *
+ * @param rule the rule
+ */
TwelveHourField(NumberRule rule) {
mRule = rule;
}
+ /**
+ * {@inheritDoc}
+ */
public int estimateLength() {
return mRule.estimateLength();
}
+ /**
+ * {@inheritDoc}
+ */
public void appendTo(StringBuffer buffer, Calendar calendar) {
int value = calendar.get(Calendar.HOUR);
if (value == 0) {
@@ -1159,6 +1462,9 @@
mRule.appendTo(buffer, value);
}
+ /**
+ * {@inheritDoc}
+ */
public void appendTo(StringBuffer buffer, int value) {
mRule.appendTo(buffer, value);
}
@@ -1170,14 +1476,26 @@
private static class TwentyFourHourField implements NumberRule {
private final NumberRule mRule;
+ /**
+ * Constructs an instance of TwentyFourHourField
with the specified
+ * NumberRule
.
+ *
+ * @param rule the rule
+ */
TwentyFourHourField(NumberRule rule) {
mRule = rule;
}
+ /**
+ * {@inheritDoc}
+ */
public int estimateLength() {
return mRule.estimateLength();
}
+ /**
+ * {@inheritDoc}
+ */
public void appendTo(StringBuffer buffer, Calendar calendar) {
int value = calendar.get(Calendar.HOUR_OF_DAY);
if (value == 0) {
@@ -1186,6 +1504,9 @@
mRule.appendTo(buffer, value);
}
+ /**
+ * {@inheritDoc}
+ */
public void appendTo(StringBuffer buffer, int value) {
mRule.appendTo(buffer, value);
}
@@ -1202,6 +1523,14 @@
private final String mStandard;
private final String mDaylight;
+ /**
+ * Constructs an instance of TimeZoneNameRule
with the specified properties.
+ *
+ * @param timeZone the time zone
+ * @param timeZoneForced if true
the time zone is forced into standard and daylight
+ * @param locale the locale
+ * @param style the style
+ */
TimeZoneNameRule(TimeZone timeZone, boolean timeZoneForced, Locale locale, int style) {
mTimeZone = timeZone;
mTimeZoneForced = timeZoneForced;
@@ -1217,6 +1546,9 @@
}
}
+ /**
+ * {@inheritDoc}
+ */
public int estimateLength() {
if (mTimeZoneForced) {
return Math.max(mStandard.length(), mDaylight.length());
@@ -1227,6 +1559,9 @@
}
}
+ /**
+ * {@inheritDoc}
+ */
public void appendTo(StringBuffer buffer, Calendar calendar) {
if (mTimeZoneForced) {
if (mTimeZone.useDaylightTime() && calendar.get(Calendar.DST_OFFSET) != 0) {
@@ -1255,14 +1590,25 @@
final boolean mColon;
+ /**
+ * Constructs an instance of TimeZoneNumberRule
with the specified properties.
+ *
+ * @param colon add colon between HH and MM in the output if true
+ */
TimeZoneNumberRule(boolean colon) {
mColon = colon;
}
+ /**
+ * {@inheritDoc}
+ */
public int estimateLength() {
return 5;
}
+ /**
+ * {@inheritDoc}
+ */
public void appendTo(StringBuffer buffer, Calendar calendar) {
int offset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET);
@@ -1296,6 +1642,14 @@
private final int mStyle;
private final Locale mLocale;
+ /**
+ * Constructs an instance of TimeZoneDisplayKey
with the specified properties.
+ *
+ * @param timeZone the time zone
+ * @param daylight adjust the style for daylight saving time if true
+ * @param style the timezone style
+ * @param locale the timezone locale
+ */
TimeZoneDisplayKey(TimeZone timeZone,
boolean daylight, int style, Locale locale) {
mTimeZone = timeZone;
@@ -1306,10 +1660,16 @@
mLocale = locale;
}
+ /**
+ * {@inheritDoc}
+ */
public int hashCode() {
return mStyle * 31 + mLocale.hashCode();
}
+ /**
+ * {@inheritDoc}
+ */
public boolean equals(Object obj) {
if (this == obj) {
return true;
@@ -1336,11 +1696,19 @@
private final Object mObj1;
private final Object mObj2;
+ /**
+ * Constructs an instance of Pair
to hold the specified objects.
+ * @param obj1 one object in the pair
+ * @param obj2 second object in the pair
+ */
public Pair(Object obj1, Object obj2) {
mObj1 = obj1;
mObj2 = obj2;
}
+ /**
+ * {@inheritDoc}
+ */
public boolean equals(Object obj) {
if (this == obj) {
return true;
@@ -1359,12 +1727,18 @@
key.mObj2 == null : mObj2.equals(key.mObj2));
}
+ /**
+ * {@inheritDoc}
+ */
public int hashCode() {
return
(mObj1 == null ? 0 : mObj1.hashCode()) +
(mObj2 == null ? 0 : mObj2.hashCode());
}
+ /**
+ * {@inheritDoc}
+ */
public String toString() {
return "[" + mObj1 + ':' + mObj2 + ']';
}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/time/StopWatch.java
===================================================================
diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa
--- 3rdParty_sources/commons-lang/org/apache/commons/lang/time/StopWatch.java (.../StopWatch.java) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4)
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/time/StopWatch.java (.../StopWatch.java) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa)
@@ -1,201 +1,342 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowledgement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgement may appear in the software itself,
- * if and wherever such third-party acknowledgements normally appear.
- *
- * 4. The names "The Jakarta Project", "Commons", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * StopWatch
provides a convenient API for timings.
+ * StopWatch
provides a convenient API for timings.
+ *
The methods do not protect against inappropriate calls. Thus you - * can call stop before start, resume before suspend or unsplit before split. - * The results are indeterminate in these cases.
- * - *To start the watch, call {@link #start()}. At this point you can:
+ *+ * To start the watch, call {@link #start()}. At this point you can: + *
*It is intended that the output methods {@link #toString()} and {@link #getTime()} - * should only be called after stop, split or suspend, however a suitable result will - * be returned at other points.
- * - * @author Henri Yandell - * @author Stephen Colebourne + * + *+ * It is intended that the output methods {@link #toString()} and {@link #getTime()} should only be called after stop, + * split or suspend, however a suitable result will be returned at other points. + *
+ * + *+ * NOTE: As from v2.1, the methods protect against inappropriate calls. Thus you cannot now call stop before start, + * resume before suspend or unsplit before split. + *
+ * + *
+ * 1. split(), suspend(), or stop() cannot be invoked twice
+ * 2. unsplit() may only be called if the watch has been split()
+ * 3. resume() may only be called if the watch has been suspend()
+ * 4. start() cannot be called twice without calling reset()
+ *
This class is not thread-safe
+ * + * @author Apache Software Foundation * @since 2.0 * @version $Id$ */ public class StopWatch { - + + // running states + private static final int STATE_UNSTARTED = 0; + + private static final int STATE_RUNNING = 1; + + private static final int STATE_STOPPED = 2; + + private static final int STATE_SUSPENDED = 3; + + // split state + private static final int STATE_UNSPLIT = 10; + + private static final int STATE_SPLIT = 11; + /** + * The current running state of the StopWatch. + */ + private int runningState = STATE_UNSTARTED; + + /** + * Whether the stopwatch has a split time recorded. + */ + private int splitState = STATE_UNSPLIT; + + /** * The start time. */ private long startTime = -1; + /** * The stop time. */ private long stopTime = -1; /** - *Constructor.
+ *+ * Constructor. + *
*/ public StopWatch() { + super(); } /** - *Start the stopwatch.
+ *+ * Start the stopwatch. + *
* - *This method starts a new timing session, clearing any previous values.
+ *+ * This method starts a new timing session, clearing any previous values. + *
+ * + * @throws IllegalStateException + * if the StopWatch is already running. */ public void start() { - stopTime = -1; - startTime = System.currentTimeMillis(); + if (this.runningState == STATE_STOPPED) { + throw new IllegalStateException("Stopwatch must be reset before being restarted. "); + } + if (this.runningState != STATE_UNSTARTED) { + throw new IllegalStateException("Stopwatch already started. "); + } + this.stopTime = -1; + this.startTime = System.currentTimeMillis(); + this.runningState = STATE_RUNNING; } /** - *Stop the stopwatch.
+ *+ * Stop the stopwatch. + *
* - *This method ends a new timing session, allowing the time to be retrieved.
+ *+ * This method ends a new timing session, allowing the time to be retrieved. + *
+ * + * @throws IllegalStateException + * if the StopWatch is not running. */ public void stop() { - stopTime = System.currentTimeMillis(); + if (this.runningState != STATE_RUNNING && this.runningState != STATE_SUSPENDED) { + throw new IllegalStateException("Stopwatch is not running. "); + } + if (this.runningState == STATE_RUNNING) { + this.stopTime = System.currentTimeMillis(); + } + this.runningState = STATE_STOPPED; } /** - *Reset the stopwatch.
+ *+ * Resets the stopwatch. Stops it if need be. + *
* - *This method clears the internal values to allow the object to be reused.
+ *+ * This method clears the internal values to allow the object to be reused. + *
*/ public void reset() { - startTime = -1; - stopTime = -1; + this.runningState = STATE_UNSTARTED; + this.splitState = STATE_UNSPLIT; + this.startTime = -1; + this.stopTime = -1; } /** - *Split the time.
+ *+ * Split the time. + *
* - *This method sets the stop time of the watch to allow a time to be extracted. - * The start time is unaffected, enabling {@link #unsplit()} to contine the - * timing from the original start point.
+ *+ * This method sets the stop time of the watch to allow a time to be extracted. The start time is unaffected, + * enabling {@link #unsplit()} to continue the timing from the original start point. + *
+ * + * @throws IllegalStateException + * if the StopWatch is not running. */ public void split() { - stopTime = System.currentTimeMillis(); + if (this.runningState != STATE_RUNNING) { + throw new IllegalStateException("Stopwatch is not running. "); + } + this.stopTime = System.currentTimeMillis(); + this.splitState = STATE_SPLIT; } /** - *Remove a split.
+ *+ * Remove a split. + *
* - *This method clears the stop time. The start time is unaffected, enabling - * timing from the original start point to continue.
+ *+ * This method clears the stop time. The start time is unaffected, enabling timing from the original start point to + * continue. + *
+ * + * @throws IllegalStateException + * if the StopWatch has not been split. */ public void unsplit() { - stopTime = -1; + if (this.splitState != STATE_SPLIT) { + throw new IllegalStateException("Stopwatch has not been split. "); + } + this.stopTime = -1; + this.splitState = STATE_UNSPLIT; } /** - *Suspend the stopwatch for later resumption.
+ *+ * Suspend the stopwatch for later resumption. + *
* - *This method suspends the watch until it is resumed. The watch will not include - * time between the suspend and resume calls in the total time.
+ *+ * This method suspends the watch until it is resumed. The watch will not include time between the suspend and + * resume calls in the total time. + *
+ * + * @throws IllegalStateException + * if the StopWatch is not currently running. */ public void suspend() { - stopTime = System.currentTimeMillis(); + if (this.runningState != STATE_RUNNING) { + throw new IllegalStateException("Stopwatch must be running to suspend. "); + } + this.stopTime = System.currentTimeMillis(); + this.runningState = STATE_SUSPENDED; } /** - *Resume the stopwatch after a suspend.
+ *+ * Resume the stopwatch after a suspend. + *
* - *This method resumes the watch after it was suspended. The watch will not include - * time between the suspend and resume calls in the total time.
+ *+ * This method resumes the watch after it was suspended. The watch will not include time between the suspend and + * resume calls in the total time. + *
+ * + * @throws IllegalStateException + * if the StopWatch has not been suspended. */ public void resume() { - startTime += (System.currentTimeMillis() - stopTime); - stopTime = -1; + if (this.runningState != STATE_SUSPENDED) { + throw new IllegalStateException("Stopwatch must be suspended to resume. "); + } + this.startTime += (System.currentTimeMillis() - this.stopTime); + this.stopTime = -1; + this.runningState = STATE_RUNNING; } /** - *Get the time on the stopwatch.
+ *+ * Get the time on the stopwatch. + *
* - *This is either the time between start and latest split, between start - * and stop, or the time between the start and the moment this method is called.
+ *+ * This is either the time between the start and the moment this method is called, or the amount of time between + * start and stop. + *
* * @return the time in milliseconds */ public long getTime() { - if (stopTime == -1) { - if (startTime == -1) { - return 0; - } - return (System.currentTimeMillis() - this.startTime); + if (this.runningState == STATE_STOPPED || this.runningState == STATE_SUSPENDED) { + return this.stopTime - this.startTime; + } else if (this.runningState == STATE_UNSTARTED) { + return 0; + } else if (this.runningState == STATE_RUNNING) { + return System.currentTimeMillis() - this.startTime; } - return (this.stopTime - this.startTime); + throw new RuntimeException("Illegal running state has occured. "); } /** - *Gets a summary of the time that the stopwatch recorded as a string.
+ *+ * Get the split time on the stopwatch. + *
* - *The format used is ISO8601-like, - * hours:minutes:seconds.milliseconds.
+ *+ * This is the time between start and latest split. + *
* + * @return the split time in milliseconds + * + * @throws IllegalStateException + * if the StopWatch has not yet been split. + * @since 2.1 + */ + public long getSplitTime() { + if (this.splitState != STATE_SPLIT) { + throw new IllegalStateException("Stopwatch must be split to get the split time. "); + } + return this.stopTime - this.startTime; + } + + /** + * Returns the time this stopwatch was started. + * + * @return the time this stopwatch was started + * @throws IllegalStateException + * if this StopWatch has not been started + * @since 2.4 + */ + public long getStartTime() { + if (this.runningState == STATE_UNSTARTED) { + throw new IllegalStateException("Stopwatch has not been started"); + } + return this.startTime; + } + + /** + *+ * Gets a summary of the time that the stopwatch recorded as a string. + *
+ * + *+ * The format used is ISO8601-like, hours:minutes:seconds.milliseconds. + *
+ * * @return the time as a String */ public String toString() { - return DurationFormatUtils.formatISO(getTime()); + return DurationFormatUtils.formatDurationHMS(getTime()); } + /** + *+ * Gets a summary of the split time that the stopwatch recorded as a string. + *
+ * + *+ * The format used is ISO8601-like, hours:minutes:seconds.milliseconds. + *
+ * + * @return the split time as a String + * @since 2.1 + */ + public String toSplitString() { + return DurationFormatUtils.formatDurationHMS(getSplitTime()); + } + } Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/time/package.html =================================================================== diff -u -r3d0166b43ce990fd9f27c433a1c58cc61085ecf4 -r6aa36ddefbf750d2b246992fee82df738a66eefa --- 3rdParty_sources/commons-lang/org/apache/commons/lang/time/package.html (.../package.html) (revision 3d0166b43ce990fd9f27c433a1c58cc61085ecf4) +++ 3rdParty_sources/commons-lang/org/apache/commons/lang/time/package.html (.../package.html) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa) @@ -1,3 +1,19 @@ +@@ -11,5 +27,6 @@
StopWatch
- a duration timer
@since 2.0
+These classes are immutable (and therefore thread-safe) apart from {@link StopWatch}.
Index: 3rdParty_sources/versions.txt =================================================================== diff -u -r36ff2c2d4199901f289b1d35e61af2b9a2a93af2 -r6aa36ddefbf750d2b246992fee82df738a66eefa --- 3rdParty_sources/versions.txt (.../versions.txt) (revision 36ff2c2d4199901f289b1d35e61af2b9a2a93af2) +++ 3rdParty_sources/versions.txt (.../versions.txt) (revision 6aa36ddefbf750d2b246992fee82df738a66eefa) @@ -11,7 +11,7 @@ Commons HttpClient 3.0 -Commons Lang 2.0 +Commons Lang 2.6 Commons IO 2.1